# TheoryBodies

body:
  %-------------------------------------------------------------------------
  %
  %  Monotonically increasing, decreasing, nonincreasing, and nondecreasing
  %  functions.
  %
  %  For PVS version 3.2.  January 13, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[D], orders[R], relation_props2[D, D, D, D],
  %    relation_props2[R, R, R, R], relations[D], relations[R]
  %  orders: closure_ops[D], closure_ops[R], indexed_sets_extra,
  %    monotone_functions[D,R], relation_iterate[D], relation_iterate[R],
  %    relations_extra[D], relations_extra[R]
  %
  %-------------------------------------------------------------------------
  monotone_functions[D: TYPE, R: TYPE]: THEORY
   BEGIN

    IMPORTING closure_ops[D], closure_ops[R]

    d1, d2: VAR D
    r1, r2: VAR R
    f: VAR [D -> R]
    Drel: VAR pred[[D, D]]
    Rrel: VAR pred[[R, R]]
    Dtot: VAR (total_order?[D])
    Dstr: VAR (strict_total_order?[D])

    increasing?(Drel, Rrel)(f): bool =
        preserves(f, irreflexive_kernel(Drel), irreflexive_kernel(Rrel))

    nonincreasing?(Drel, Rrel)(f): bool =
        inverts(f, reflexive_closure(Drel), reflexive_closure(Rrel))

    decreasing?(Drel, Rrel)(f): bool =
        inverts(f, irreflexive_kernel(Drel), irreflexive_kernel(Rrel))

    nondecreasing?(Drel, Rrel)(f): bool =
        preserves(f, reflexive_closure(Drel), reflexive_closure(Rrel))

    increasing_is_nondecreasing: THEOREM
      FORALL Drel, Rrel, f:
        increasing?(Drel, Rrel)(f) IMPLIES nondecreasing?(Drel, Rrel)(f)

    decreasing_is_nonincreasing: THEOREM
      FORALL Drel, Rrel, f:
        decreasing?(Drel, Rrel)(f) IMPLIES nonincreasing?(Drel, Rrel)(f)

    not_increasing_and_nonincreasing: THEOREM
      (EXISTS d1, d2: d1 /= d2) IMPLIES
       (FORALL (Drel: (trichotomous?[D])), (Rrel: (antisymmetric?[R])), f:
          NOT (increasing?(Drel, Rrel)(f) AND nonincreasing?(Drel, Rrel)(f)))

    not_decreasing_and_nondecreasing: THEOREM
      (EXISTS d1, d2: d1 /= d2) IMPLIES
       (FORALL (Drel: (trichotomous?[D])), (Rrel: (antisymmetric?[R])), f:
          NOT (decreasing?(Drel, Rrel)(f) AND nondecreasing?(Drel, Rrel)(f)))

    increasing_converse_decreasing1: THEOREM
      FORALL Drel, Rrel:
        increasing?(Drel, Rrel) = decreasing?(Drel, converse(Rrel))

    increasing_converse_decreasing2: THEOREM
      FORALL Drel, Rrel:
        increasing?(Drel, Rrel) = decreasing?(converse(Drel), Rrel)

    nonincreasing_converse_nondecreasing1: THEOREM
      FORALL Drel, Rrel:
        nonincreasing?(Drel, Rrel) = nondecreasing?(Drel, converse(Rrel))

    nonincreasing_converse_nondecreasing2: THEOREM
      FORALL Drel, Rrel:
        nonincreasing?(Drel, Rrel) = nondecreasing?(converse(Drel), Rrel)

    increasing_total_order_injective: THEOREM
      FORALL Dtot, Rrel, f: increasing?(Dtot, Rrel)(f) IMPLIES injective?(f)

    increasing_strict_total_order_injective: THEOREM
      FORALL Dstr, Rrel, f: increasing?(Dstr, Rrel)(f) IMPLIES injective?(f)

    decreasing_total_order_injective: THEOREM
      FORALL Dtot, Rrel, f: decreasing?(Dtot, Rrel)(f) IMPLIES injective?(f)

    decreasing_strict_total_order_injective: THEOREM
      FORALL Dstr, Rrel, f: decreasing?(Dstr, Rrel)(f) IMPLIES injective?(f)

   END monotone_functions


body:
  %-------------------------------------------------------------------------
  %
  %  Properties of well-ordered relations on sets.
  %
  %  For PVS version 3.2.  February 28, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: relation_props2[T, T, T, T], sets[T]
  %  orders: closure_ops[T], indexed_sets_extra, isomorphism,
  %    monotone_functions[T,T], ordered_subset[T], relation_iterate[T],
  %    relations_extra, well_ordered_props[T,<]
  %
  %-------------------------------------------------------------------------
  well_ordered_props[T: TYPE, <: (well_ordered?[T])]: THEORY
   BEGIN

    IMPORTING ordered_subset[T], monotone_functions[T, T], isomorphism

    t, r: VAR T
    S, R: VAR set[T]

    initial_segment: TYPE = {pre: (prefix?(<)) | EXISTS t: NOT member(t, pre)}

    seg: VAR initial_segment

    induced_prefixes: LEMMA FORALL seg: EXISTS t: seg = below(t, <)

    increasing_well_ordered: LEMMA
      FORALL (f: (increasing?(<, <))), t: t < f(t) OR t = f(t)

    initial_segment_isomorphism: COROLLARY
      FORALL seg:
        NOT isomorphic?[T, (seg)]
                (<, restrict[[T, T], [(seg), (seg)], bool](<))

   END well_ordered_props


body:
  %-------------------------------------------------------------------------
  %
  %  Sets with a strict total order and with the property that the below set
  %  of every element is finite are well orderings such that every element
  %  but the first has a previous element.
  %
  %  For PVS version 3.2.  February 28, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[T], relation_props2[T, T, T, T], relations[T], sets[T]
  %  finite_sets: finite_sets_inductions, finite_sets_minmax
  %  orders: bounded_orders[T], closure_ops[T], indexed_sets_extra,
  %    minmax_orders[T], ordered_subset[T], relation_iterate[T],
  %    relations_extra[T], well_ordered_finite[T,<],
  %    well_ordered_traversal[T]
  %
  %-------------------------------------------------------------------------
  well_ordered_finite[T: TYPE, <: (strict_total_order?[T])]: THEORY
   BEGIN

    ASSUMING
     IMPORTING ordered_subset[T]
     finite_below: ASSUMPTION FORALL (t: T): is_finite(below(t, <))
    ENDASSUMING

    IMPORTING well_ordered_traversal[T]

    t: VAR T
    S: VAR (nonempty?[T])

    nonempty_has_least: JUDGEMENT
      (nonempty?[T]) SUBTYPE_OF (has_least?(reflexive_closure(<)))

    finite_well_ordered: JUDGEMENT < HAS_TYPE (well_ordered?)

    nonlast_has_next: JUDGEMENT (nonlast(<)) SUBTYPE_OF (has_next?(<))

    nonfirst_has_prev: JUDGEMENT (nonfirst(<)) SUBTYPE_OF (has_prev?(<))

    finite_last: THEOREM has_last?(<) IMPLIES is_finite_type[T]

   END well_ordered_finite

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 35, column 4) for  x
      % expected type  (LAMBDA (S: set[T]):
                     %    has_least?(S, reflexive_closure(<)))
  nonempty_has_least: OBLIGATION
    FORALL (x: (nonempty?[T])): has_least?[T](x, reflexive_closure[T](<));

  % Judgement subtype TCC generated (at line 37, column 33) for  <
      % expected type  (well_ordered?)
  finite_well_ordered: OBLIGATION well_ordered?[T](<);

  % Judgement subtype TCC generated (at line 39, column 30) for  x
      % expected type  (has_next?(<))
  nonlast_has_next: OBLIGATION FORALL (x: (nonlast(<))): has_next?[T](<)(x);

  % Judgement subtype TCC generated (at line 41, column 31) for  x
      % expected type  (has_prev?(<))
  nonfirst_has_prev: OBLIGATION FORALL (x: (nonfirst(<))): has_prev?[T](<)(x);


body:
  %-------------------------------------------------------------------------
  %
  %  Well-orderings on sets of natural numbers.
  %
  %  For PVS version 3.2.  February 28, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: finite_sets[nat], orders[nat], sets[nat], relations[nat]
  %  finite_sets: finite_sets_inductions, finite_sets_minmax
  %  orders: bounded_orders[nat], minmax_orders[nat], relations_extra[nat],
  %    well_nat
  %
  %-------------------------------------------------------------------------
  well_nat: THEORY
   BEGIN

    IMPORTING minmax_orders[nat]

    n, m: VAR nat
    S: VAR set[nat]
    F: VAR finite_set[nat]

    well_lt_nat: THEOREM FORALL S: well_ordered?[(S)](<)

    well_gt_nat: THEOREM FORALL F: well_ordered?[(F)](>)

   END well_nat


body:
  %-------------------------------------------------------------------------
  %
  %  Every totally ordered finite set has an order-preserving bijection
  %  with a below set.
  %
  %  For PVS version 3.2.  March 5, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[T]
  %  finite_sets: finite_sets_inductions, finite_sets_minmax
  %  orders: bounded_orders[T], closure_ops[T], finite_below[T],
  %    indexed_sets_extra, minmax_orders[T], relations_extra[T],
  %    relation_iterate[T]
  %
  %-------------------------------------------------------------------------
  finite_below[T: TYPE]: THEORY
   BEGIN

    IMPORTING closure_ops[T], minmax_orders[T]

    S: VAR finite_set[T]
    <: VAR (strict_total_order?[T])

    % Select the nth element of the set

    nth(S, <)(n: below[card(S)]): RECURSIVE (S) =
      IF n = 0 THEN least(reflexive_closure(<))(S)
      ELSE nth(remove(least(reflexive_closure(<))(S), S), <)(n - 1)
      ENDIF
       MEASURE n

    nth_one_step: LEMMA
      FORALL S, <, (n: below[card(S)]):
        n + 1 < card(S) IMPLIES nth(S, <)(n) < nth(S, <)(n + 1)

    nth_monotonic: LEMMA FORALL S, <: preserves(nth(S, <), reals.<, <)

    nth_surjective: LEMMA FORALL S, <: surjective?(nth(S, <))

    nth_bijective: JUDGEMENT
        nth(S, <) HAS_TYPE (bijective?[below[card(S)], (S)])

    % Find out which element of the set this is

    index(S, <)(t: (S)): RECURSIVE below[card(S)] =
      IF least?(t, S, reflexive_closure(<)) THEN 0
      ELSE 1 + index(remove(least(reflexive_closure(<))(S), S), <)(t)
      ENDIF
       MEASURE card(S)

    index_monotonic: LEMMA
      FORALL S, <: preserves(index(S, <), <, reals.<)

    index_nth_left_inverse: LEMMA
      FORALL S, <: left_inverse?(nth(S, <), index(S, <))

    index_nth_right_inverse: LEMMA
      FORALL S, <: right_inverse?(nth(S, <), index(S, <))

    index_bijective: JUDGEMENT
        index(S, <) HAS_TYPE (bijective?[(S), below[card(S)]])

   END finite_below

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 30, column 46) for  S
      % expected type  S:
                     %   (LAMBDA (S: set[T]):
                     %      has_least?(S, reflexive_closure(<)))
  nth_TCC1: OBLIGATION
    FORALL (S: finite_set[T], <: (strict_total_order?[T]),
            n: below[card[T](S)]):
      n = 0 IMPLIES has_least?[T](S, reflexive_closure[T](<));

  % Subtype TCC generated (at line 31, column 48) for  S
      % expected type  S:
                     %   (LAMBDA (S: set[T]):
                     %      has_least?(S, reflexive_closure(<)))
  nth_TCC2: OBLIGATION
    FORALL (S: finite_set[T], <: (strict_total_order?[T]),
            n: below[card[T](S)]):
      NOT n = 0 IMPLIES has_least?[T](S, reflexive_closure[T](<));

  % Subtype TCC generated (at line 31, column 59) for  n - 1
      % expected type  below[card(remove(least(reflexive_closure(<))(S), S))]
  nth_TCC3: OBLIGATION
    FORALL (S: finite_set[T], <: (strict_total_order?[T]),
            n: below[card[T](S)]):
      NOT n = 0 IMPLIES
       n - 1 >= 0 AND
        n - 1 < card[T](remove[T](least[T](reflexive_closure[T](<))(S), S));

  % Termination TCC generated (at line 31, column 9) for
      % nth(remove(least(reflexive_closure(<))(S), S), <)(n - 1)
  nth_TCC4: OBLIGATION
    FORALL (S: finite_set[T], <: (strict_total_order?[T]),
            n: below[card[T](S)]):
      NOT n = 0 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 31, column 9) for
      % nth(remove(least(reflexive_closure(<))(S), S), <)(n - 1)
      % expected type  (S)
  nth_TCC5: OBLIGATION
    FORALL (S: finite_set[T], <: (strict_total_order?[T]),
            n: below[card[T](S)],
            v:
              [d1: [finite_set[T], (strict_total_order?[T])] ->
                 [{z: below[card(d1`1)] | z < n} -> (d1`1)]]):
      NOT n = 0 IMPLIES
       S(v(remove[T](least[T](reflexive_closure[T](<))(S), S), <)(n - 1));

  % Judgement subtype TCC generated (at line 44, column 6) for  nth(S, <)
      % expected type  (bijective?[below[card(S)], (S)])
  nth_bijective: OBLIGATION
    FORALL (<, S): bijective?[below[card[T](S)], (S)](nth(S, <));

  % Subtype TCC generated (at line 49, column 47) for  0
      % expected type  below[card(S)]
  index_TCC1: OBLIGATION
    FORALL (S: finite_set[T], <: (strict_total_order?[T]), t: (S)):
      least?(t, S, reflexive_closure(<)) IMPLIES 0 < card[T](S);

  % Subtype TCC generated (at line 50, column 65) for  t
      % expected type  (remove(least(reflexive_closure(<))(S), S))
  index_TCC2: OBLIGATION
    FORALL (S: finite_set[T], <: (strict_total_order?[T]), t: (S)):
      NOT least?(t, S, reflexive_closure(<)) IMPLIES
       remove[T](least[T](reflexive_closure[T](<))(S), S)(t);

  % Subtype TCC generated (at line 50, column 54) for  S
      % expected type  S:
                     %   (LAMBDA (S: set[T]):
                     %      has_least?(S, reflexive_closure(<)))
  index_TCC3: OBLIGATION
    FORALL (S: finite_set[T], <: (strict_total_order?[T]), t: (S)):
      NOT least?(t, S, reflexive_closure(<)) IMPLIES
       has_least?[T](S, reflexive_closure[T](<));

  % Termination TCC generated (at line 50, column 13) for
      % index(remove(least(reflexive_closure(<))(S), S), <)
  index_TCC4: OBLIGATION
    FORALL (S: finite_set[T], <: (strict_total_order?[T]), t: (S)):
      NOT least?(t, S, reflexive_closure(<)) IMPLIES
       card[T](remove[T](least[T](reflexive_closure[T](<))(S), S)) <
        card[T](S);

  % Subtype TCC generated (at line 50, column 9) for
      % 1 + index(remove(least(reflexive_closure(<))(S), S), <)(t)
      % expected type  below[card(S)]
  index_TCC5: OBLIGATION
    FORALL (S: finite_set[T],
            v:
              [d1:
                 {z: [finite_set[T], (strict_total_order?[T])] |
                          card(z`1) < card(S)} ->
                 [(d1`1) -> below[card(d1`1)]]],
            <: (strict_total_order?[T]), t: (S)):
      NOT least?(t, S, reflexive_closure(<)) IMPLIES
       1 + v(remove[T](least[T](reflexive_closure[T](<))(S), S), <)(t) <
        card[T](S);

  % Judgement subtype TCC generated (at line 64, column 6) for  index(S, <)
      % expected type  (bijective?[(S), below[card(S)]])
  index_bijective: OBLIGATION
    FORALL (<, S): bijective?[(S), below[card[T](S)]](index(S, <));


body:
  %-------------------------------------------------------------------------
  %
  %  Similar ordered sets.  Two totally ordered sets are similar if there
  %  exists an bijective function from the first to the second that
  %  preserves ordering.  This is a special case of isomorphism.
  %
  %  For PVS version 3.2.  March 5, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[D], orders[R]
  %  orders: isomorphism[D,R], similarity[D,R]
  %
  %-------------------------------------------------------------------------
  similarity[D: TYPE, R: TYPE]: THEORY
   BEGIN

    IMPORTING isomorphism[D, R]

    Dord: VAR (total_order?[D])
    Rord: VAR (total_order?[R])
    f: VAR (bijective?[D, R])

    similarity?(Dord, Rord)(f): bool = preserves(f, Dord, Rord)

    similar?(Dord, Rord): bool = EXISTS f: similarity?(Dord, Rord)(f)

    similarity_is_isomorphism: LEMMA
      FORALL Dord, Rord, f:
        similarity?(Dord, Rord)(f) IMPLIES isomorphism?(Dord, Rord)(f)

    similar_is_isomorphic: COROLLARY
      FORALL Dord, Rord: similar?(Dord, Rord) IMPLIES isomorphic?(Dord, Rord)

   END similarity


body:
  %-------------------------------------------------------------------------
  %
  %  Properties of similar sets.
  %
  %  For PVS version 3.2.  March 5, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[D], orders[R]
  %  finite_sets: finite_sets_inductions, finite_sets_minmax
  %  orders: bounded_orders[D], bounded_orders[R], closure_ops[D],
  %    closure_ops[R], finite_below[D], finite_below[R], indexed_sets_extra,
  %    isomorphism[D,R], minmax_orders[D], minmax_orders[R],
  %    relations_extra[D], relations_extra[R], relation_iterate[D],
  %    relation_iterate[R], similarity[D,R], similarity_props[D,R]
  %
  %-------------------------------------------------------------------------
  similarity_props[D: TYPE, R: TYPE]: THEORY
   BEGIN

    IMPORTING minmax_orders[D], minmax_orders[R]
    IMPORTING similarity[D, R], finite_below[D], finite_below[R]

    Dord: VAR (total_order?[D])
    Rord: VAR (total_order?[R])
    f: VAR (bijective?[D, R])
    d: VAR D

    similarity_greatest: LEMMA
      FORALL Dord, Rord, f, d:
        similarity?(Dord, Rord)(f) AND greatest?(d, fullset[D], Dord) IMPLIES
         greatest?(f(d), fullset[R], Rord)

    similar_has_greatest: COROLLARY
      FORALL Dord, Rord:
        similar?(Dord, Rord) AND has_greatest?(fullset[D], Dord) IMPLIES
         has_greatest?(fullset[R], Rord)

    similarity_least: LEMMA
      FORALL Dord, Rord, f, d:
        similarity?(Dord, Rord)(f) AND least?(d, fullset[D], Dord) IMPLIES
         least?(f(d), fullset[R], Rord)

    similar_has_least: COROLLARY
      FORALL Dord, Rord:
        similar?(Dord, Rord) AND has_least?(fullset[D], Dord) IMPLIES
         has_least?(fullset[R], Rord)

    similar_finite: LEMMA
      is_finite_type[D] AND
       is_finite_type[R] AND card(fullset[D]) = card(fullset[R])
       IMPLIES (FORALL Dord, Rord: similar?(Dord, Rord))

   END similarity_props

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 53, column 32) for  fullset[D]
      % expected type  S: finite_set[D]
  similar_finite_TCC1: OBLIGATION
    is_finite_type[D] AND is_finite_type[R] IMPLIES is_finite[D](fullset[D]);

  % Subtype TCC generated (at line 53, column 51) for  fullset[R]
      % expected type  S: finite_set[R]
  similar_finite_TCC2: OBLIGATION
    is_finite_type[D] AND is_finite_type[R] IMPLIES is_finite[R](fullset[R]);


body:
  %-------------------------------------------------------------------------
  %
  %  There is an injective (surjective) map between any pair of sets.
  %  We have to special case empty sets because, if the range is empty,
  %  there is NO function from nonempty D to R.
  %
  %  For PVS version 3.2.  January 18, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: sets_lemmas[D]
  %  orders: set_dichotomous[D, R]
  %
  %-------------------------------------------------------------------------
  set_dichotomous[D: TYPE, R: TYPE]: THEORY

   % Hide uninteresting intermediate results
   EXPORTING injective_or_surjective, injective_dichotomous,
             surjective_dichotomous WITH sets_lemmas[D]

   BEGIN

    IMPORTING sets_lemmas[D], function_inverse_def[D, R]

    % ==========================================================================
    % Declarations used for the proofs only
    % ==========================================================================

    subset_injection: TYPE = [S: set[D], (injective?[(S), R])]

    d: VAR D
    r: VAR R
    i, j: VAR subset_injection

    injection_order(i, j): bool =
        subset?(i`1, j`1) AND (FORALL (d: (i`1)): i`2(d) = j`2(d))

    partial_injection_order: JUDGEMENT
      injection_order HAS_TYPE (partial_order?[subset_injection])

    IMPORTING zorn[subset_injection, injection_order]


    % ==========================================================================
    % The theorems
    % ==========================================================================

    injective_or_surjective: THEOREM
      (EXISTS (f: [D -> R]): injective?(f)) OR
      (EXISTS (f: [D -> R]): surjective?(f)) OR
      ((EXISTS d: TRUE) AND (FORALL r: FALSE))

    injective_dichotomous: COROLLARY
      (EXISTS (f: [D -> R]): injective?(f)) OR
      (EXISTS (f: [R -> D]): injective?(f))
      
    surjective_dichotomous: COROLLARY
      (EXISTS (f: [D -> R]): surjective?(f)) OR
      (EXISTS (f: [R -> D]): surjective?(f)) OR
      ((EXISTS d: TRUE) AND (FORALL r: FALSE)) OR
      ((FORALL d: FALSE) AND (EXISTS r: TRUE))

   END set_dichotomous

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 38, column 61) for  d
      % expected type  (j`1)
  injection_order_TCC1: OBLIGATION
    FORALL (i: subset_injection, j: subset_injection):
      subset?(i`1, j`1) IMPLIES (FORALL (d: (i`1)): j`1(d));

  % Judgement subtype TCC generated (at line 41, column 4) for  injection_order
      % expected type  (partial_order?[subset_injection])
  partial_injection_order: OBLIGATION
    partial_order?[subset_injection](injection_order);


body:
  %-------------------------------------------------------------------------
  %
  %  If there are injective (surjective) maps both ways between two sets,
  %  then the sets are bijective.
  %
  %  For PVS version 3.2.  January 18, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  orders: set_antisymmetric[D, R]
  %
  %-------------------------------------------------------------------------
  set_antisymmetric[D: TYPE, R: TYPE]: THEORY
   BEGIN

    in_closure(f: [D -> R], g: [R -> D], d: D): INDUCTIVE bool =
      member(d, complement(image(g, fullset[R]))) OR
      (EXISTS (e: D): g(f(e)) = d AND in_closure(f, g, e))

    % The Schroeder-Bernstein Theorem
    inj_inj_bij: THEOREM
      (EXISTS (f: [D -> R]): injective?(f)) AND
       (EXISTS (f: [R -> D]): injective?(f))
       => (EXISTS (f: [D -> R]): bijective?(f))

    surj_surj_bij: COROLLARY
      (EXISTS (f: [D -> R]): surjective?(f)) AND
       (EXISTS (f: [R -> D]): surjective?(f))
       => (EXISTS (f: [D -> R]): bijective?(f))

    inj_surj_bij: COROLLARY
      (EXISTS (f: [D -> R]): injective?(f)) AND
       (EXISTS (f: [D -> R]): surjective?(f))
       => (EXISTS (f: [D -> R]): bijective?(f))

   END set_antisymmetric

addendum:
  %%% ================ Addendum: generated declarations ================

  in_closure_weak_induction: AXIOM
    FORALL (f: [D -> R], g: [R -> D], P: [D -> boolean]):
      (FORALL (d: D):
         member(d, complement(image(g, fullset[R]))) OR
          (EXISTS (e: D): g(f(e)) = d AND P(e))
          IMPLIES P(d))
       IMPLIES (FORALL (d: D): in_closure(f, g, d) IMPLIES P(d));

  in_closure_induction: AXIOM
    FORALL (f: [D -> R], g: [R -> D], P: [D -> boolean]):
      (FORALL (d: D):
         member(d, complement(image(g, fullset[R]))) OR
          (EXISTS (e: D): g(f(e)) = d AND in_closure(f, g, e) AND P(e))
          IMPLIES P(d))
       IMPLIES (FORALL (d: D): in_closure(f, g, d) IMPLIES P(d));


body:
  %-------------------------------------------------------------------------
  %
  %  Infinite numeric types.
  %
  %  For PVS version 3.2.  March 3, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  orders: numbers_infinite
  %
  %-------------------------------------------------------------------------
  numbers_infinite: THEORY
   BEGIN

    nat_infinite: LEMMA NOT is_finite_type[nat]

    int_infinite: LEMMA NOT is_finite_type[int]

    rat_infinite: LEMMA NOT is_finite_type[rat]

    real_infinite: LEMMA NOT is_finite_type[real]

   END numbers_infinite


body:
  %-------------------------------------------------------------------------
  %
  %  Ranges of numbers.
  %
  %  For PVS version 3.2.  February 8, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: finite_sets[T], orders[T], relations[T], sets[T]
  %  finite_sets: finite_sets_inductions, finite_sets_minmax
  %  orders: bounded_orders[T], minmax_orders[T], range[T],
  %    relations_extra[T]
  %
  %-------------------------------------------------------------------------
  range[T: TYPE+ FROM real]: THEORY
   BEGIN

    IMPORTING minmax_orders[T]

    t, r, r1, r2: VAR T
    S: VAR set[T]

    % A convenient shorthand
    lesseq: MACRO pred[[T, T]] = restrict[[real, real], [T, T], boolean](<=)

    % Minima- and maxima-related definitions for open/closed ranges
    has_non_least?(S): bool =
        EXISTS r:
          (FORALL (t: (S)): r < t) AND
           (FORALL r1: (FORALL (t: (S)): r1 < t) IMPLIES r1 <= r)

    has_non_greatest?(S): bool =
        EXISTS r:
          (FORALL (t: (S)): t < r) AND
           (FORALL r1: (FORALL (t: (S)): t < r1) IMPLIES r <= r1)

    not_has_least?(S): MACRO bool =
        (NOT has_least?(S, lesseq)) OR has_non_least?(S)

    not_has_greatest?(S): MACRO bool =
        (NOT has_greatest?(S, lesseq)) OR has_non_greatest?(S)


    % ==========================================================================
    % The base range type
    % ==========================================================================

    range: TYPE+ =
      {S | FORALL (lo, hi: (S)), r: lo <= r AND r <= hi IMPLIES member(r, S)}

    R: VAR range


    % ==========================================================================
    % Ranges with maxima and minima
    % ==========================================================================

    min_range: TYPE+ = {R | has_least?(R, lesseq)}
    max_range: TYPE+ = {R | has_greatest?(R, lesseq)}


    % ==========================================================================
    % Ranges with no greatest lower or least upper element
    % ==========================================================================

    no_least(t): bool = NOT has_least?({r | r <= t}, lesseq)
    no_greatest(t): bool = NOT has_greatest?({r | t <= r}, lesseq)


    % ==========================================================================
    % Closed, open, closed/open, and open/closed ranges
    % ==========================================================================

    c_range:  TYPE+ = {R | has_least?(R, lesseq) AND has_greatest?(R, lesseq)}
    oc_range: TYPE  = {R | not_has_least?(R) AND has_greatest?(R, lesseq)}
    co_range: TYPE  = {R | has_least?(R, lesseq) AND not_has_greatest?(R)}
    o_range:  TYPE+ = {R | not_has_least?(R) AND not_has_greatest?(R)}

    % The nontrivial range types
    ntc_range: TYPE = {R: c_range | least(lesseq)(R) < greatest(lesseq)(R)}
    nto_range: TYPE = {R: o_range | nonempty?(R)}

    % Non-open ranges are nonempty
    c_range_is_nonempty:   JUDGEMENT c_range   SUBTYPE_OF (nonempty?[T])
    ntc_range_is_nonempty: JUDGEMENT ntc_range SUBTYPE_OF (nonempty?[T])
    oc_range_is_nonempty:  JUDGEMENT oc_range  SUBTYPE_OF (nonempty?[T])
    co_range_is_nonempty:  JUDGEMENT co_range  SUBTYPE_OF (nonempty?[T])


    % ==========================================================================
    % Constructing ranges
    % ==========================================================================

    % Constructing bounded ranges
    closed_range(r1, (r2: {r | r1 <= r})): c_range = {r | r1 <= r AND r <= r2}
    nontrivial_closed_range(r1, (r2: {r | r1 < r})): ntc_range =
        {r | r1 <= r AND r <= r2}
    open_closed_range(r1, (r2: {r | r1 < r})): oc_range =
        {r | r1 < r AND r <= r2}
    closed_open_range(r1, (r2: {r | r1 < r})): co_range =
        {r | r1 <= r AND r < r2}
    open_range(r1, r2): o_range = {r | r1 < r AND r < r2}
    nontrivial_open_range(r1, (r2: {r | EXISTS t: r1 < t AND t < r})):
      nto_range = {r | r1 < r AND r < r2}

    % Constructing unbounded ranges
    open_closed_range(r: (no_least)): oc_range = {r1 | r1 <= r}
    closed_open_range(r: (no_greatest)): co_range = {r1 | r <= r1}
    left_open_range(r: (no_least)):  nto_range = {r1 | r1 < r}
    right_open_range(r: (no_greatest)): nto_range = {r1 | r < r1}

    % The closed constructors are complete
    c_range_construction: THEOREM
      FORALL (R: c_range):
        EXISTS r1, (r2: {r | r1 <= r}): R = closed_range(r1, r2)
    ntc_range_construction: THEOREM
      FORALL (R: ntc_range):
        EXISTS r1, (r2: {r | r1 < r}): R = nontrivial_closed_range(r1, r2)

    % least and greatest for constructed ranges
    c_range_endpoints: THEOREM
      FORALL (R: c_range): least(lesseq)(R) <= greatest(lesseq)(R)
    ntc_range_endpoints: THEOREM
      FORALL (R: ntc_range): least(lesseq)(R) < greatest(lesseq)(R)

    c_range_min: THEOREM
      FORALL r1, (r2: {r | r1 <= r}): least(lesseq)(closed_range(r1, r2)) = r1
    c_range_max: THEOREM
      FORALL r1, (r2: {r | r1 <= r}):
        greatest(lesseq)(closed_range(r1, r2)) = r2

    ntc_range_min: THEOREM
      FORALL r1, (r2: {r | r1 < r}):
        least(lesseq)(nontrivial_closed_range(r1, r2)) = r1
    ntc_range_max: THEOREM
      FORALL r1, (r2: {r | r1 < r}):
        greatest(lesseq)(nontrivial_closed_range(r1, r2)) = r2

    oc_range_max1: THEOREM
      FORALL r1, (r2: {r | r1 < r}):
        greatest(lesseq)(open_closed_range(r1, r2)) = r2
    oc_range_max2: THEOREM
      FORALL (r: (no_least)): greatest(lesseq)(open_closed_range(r)) = r

    co_range_min1: THEOREM
      FORALL r1, (r2: {r | r1 < r}):
        least(lesseq)(closed_open_range(r1, r2)) = r1
    co_range_min2: THEOREM
      FORALL (r: (no_greatest)): least(lesseq)(closed_open_range(r)) = r

   END range

addendum:
  %%% ================ Addendum: generated declarations ================

  % Existence TCC generated (at line 50, column 2) for
      % range: TYPE+ =
      %       {S |
      %                FORALL (lo, hi: (S)), r:
      %                  lo <= r AND r <= hi IMPLIES member(r, S)}
  range_TCC1: OBLIGATION
    EXISTS (x:
              {S |
                       FORALL (lo, hi: (S)), r:
                         lo <= r AND r <= hi IMPLIES member[T](r, S)}):
      TRUE;

  % Existence TCC generated (at line 60, column 2) for
      % min_range: TYPE+ =
      %       {R | has_least?(R, restrict[[real, real], [T, T], boolean](<=))}
  min_range_TCC1: OBLIGATION
    EXISTS (x:
              {R |
                       has_least?[T]
                           (R,
                            restrict[[real, real], [T, T], boolean](<=))}):
      TRUE;

  % Existence TCC generated (at line 61, column 2) for
      % max_range: TYPE+ =
      %       {R |
      %                has_greatest?(R,
      %                              restrict[[real, real], [T, T], boolean]
      %                                  (<=))}
  max_range_TCC1: OBLIGATION
    EXISTS (x:
              {R |
                       has_greatest?[T]
                           (R,
                            restrict[[real, real], [T, T], boolean](<=))}):
      TRUE;

  % Existence TCC generated (at line 76, column 2) for
      % c_range: TYPE+ =
      %       {R |
      %                has_least?(R,
      %                           restrict[[real, real], [T, T], boolean]
      %                               (<=))
      %                 AND
      %                 has_greatest?(R,
      %                               restrict[[real, real], [T, T], boolean]
      %                               (<=))}
  c_range_TCC1: OBLIGATION
    EXISTS (x:
              {R |
                       has_least?[T]
                           (R, restrict[[real, real], [T, T], boolean](<=))
                        AND
                        has_greatest?[T]
                            (R,
                             restrict[[real, real], [T, T], boolean](<=))}):
      TRUE;

  % Existence TCC generated (at line 79, column 2) for
      % o_range: TYPE+ =
      %       {R |
      %                ((NOT has_least?(R,
      %                                 restrict
      %                                 [[real, real], [T, T], boolean]
      %                                 (<=)))
      %                  OR has_non_least?(R))
      %                 AND
      %                 ((NOT has_greatest?(R,
      %                                     restrict
      %                                     [[real, real], [T, T], boolean]
      %                                     (<=)))
      %                   OR has_non_greatest?(R))}
  o_range_TCC1: OBLIGATION
    EXISTS (x:
              {R |
                       ((NOT has_least?[T]
                                 (R,
                                  restrict[[real, real], [T, T], boolean]
                                      (<=)))
                         OR has_non_least?(R))
                        AND
                        ((NOT has_greatest?[T]
                                  (R,
                                   restrict[[real, real], [T, T], boolean]
                                       (<=)))
                          OR has_non_greatest?(R))}):
      TRUE;

  % Judgement subtype TCC generated (at line 86, column 35) for  x
      % expected type  (nonempty?[T])
  c_range_is_nonempty: OBLIGATION FORALL (x: c_range): nonempty?[T](x);

  % Judgement subtype TCC generated (at line 88, column 35) for  x
      % expected type  (nonempty?[T])
  oc_range_is_nonempty: OBLIGATION FORALL (x: oc_range): nonempty?[T](x);

  % Judgement subtype TCC generated (at line 89, column 35) for  x
      % expected type  (nonempty?[T])
  co_range_is_nonempty: OBLIGATION FORALL (x: co_range): nonempty?[T](x);

  % Subtype TCC generated (at line 97, column 51) for
      % {r | r1 <= r AND r <= r2}
      % expected type  c_range
  closed_range_TCC1: OBLIGATION
    FORALL (r1: T, (r2: {r | r1 <= r})):
      (FORALL (lo, hi: ({r | r1 <= r AND r <= r2})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES
          member[T](r_1, {r | r1 <= r AND r <= r2}))
       AND
       has_least?[T]
           ({r | r1 <= r AND r <= r2},
            restrict[[real, real], [T, T], boolean](<=))
        AND
        has_greatest?[T]
            ({r | r1 <= r AND r <= r2},
             restrict[[real, real], [T, T], boolean](<=));

  % Subtype TCC generated (at line 99, column 6) for
      % {r | r1 <= r AND r <= r2}
      % expected type  ntc_range
  nontrivial_closed_range_TCC1: OBLIGATION
    FORALL (r1: T, (r2: {r | r1 < r})):
      (FORALL (lo, hi: ({r | r1 <= r AND r <= r2})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES
          member[T](r_1, {r | r1 <= r AND r <= r2}))
       AND
       (has_least?[T]
            ({r | r1 <= r AND r <= r2},
             restrict[[real, real], [T, T], boolean](<=))
         AND
         has_greatest?[T]
             ({r | r1 <= r AND r <= r2},
              restrict[[real, real], [T, T], boolean](<=)))
        AND
        least[T]
            (restrict[[real, real], [T, T], boolean](<=))
            ({r | r1 <= r AND r <= r2})
         <
         greatest[T]
             (restrict[[real, real], [T, T], boolean](<=))
             ({r | r1 <= r AND r <= r2});

  % Subtype TCC generated (at line 101, column 6) for
      % {r | r1 < r AND r <= r2}
      % expected type  oc_range
  open_closed_range_TCC1: OBLIGATION
    FORALL (r1: T, (r2: {r | r1 < r})):
      (FORALL (lo, hi: ({r | r1 < r AND r <= r2})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES
          member[T](r_1, {r | r1 < r AND r <= r2}))
       AND
       ((NOT has_least?[T]
                 ({r | r1 < r AND r <= r2},
                  restrict[[real, real], [T, T], boolean](<=)))
         OR has_non_least?({r | r1 < r AND r <= r2}))
        AND
        has_greatest?[T]
            ({r | r1 < r AND r <= r2},
             restrict[[real, real], [T, T], boolean](<=));

  % Subtype TCC generated (at line 103, column 6) for
      % {r | r1 <= r AND r < r2}
      % expected type  co_range
  closed_open_range_TCC1: OBLIGATION
    FORALL (r1: T, (r2: {r | r1 < r})):
      (FORALL (lo, hi: ({r | r1 <= r AND r < r2})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES
          member[T](r_1, {r | r1 <= r AND r < r2}))
       AND
       has_least?[T]
           ({r | r1 <= r AND r < r2},
            restrict[[real, real], [T, T], boolean](<=))
        AND
        ((NOT has_greatest?[T]
                  ({r | r1 <= r AND r < r2},
                   restrict[[real, real], [T, T], boolean](<=)))
          OR has_non_greatest?({r | r1 <= r AND r < r2}));

  % Subtype TCC generated (at line 104, column 32) for
      % {r | r1 < r AND r < r2}
      % expected type  o_range
  open_range_TCC1: OBLIGATION
    FORALL (r1: T, r2: T):
      (FORALL (lo, hi: ({r | r1 < r AND r < r2})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES
          member[T](r_1, {r | r1 < r AND r < r2}))
       AND
       ((NOT has_least?[T]
                 ({r | r1 < r AND r < r2},
                  restrict[[real, real], [T, T], boolean](<=)))
         OR has_non_least?({r | r1 < r AND r < r2}))
        AND
        ((NOT has_greatest?[T]
                  ({r | r1 < r AND r < r2},
                   restrict[[real, real], [T, T], boolean](<=)))
          OR has_non_greatest?({r | r1 < r AND r < r2}));

  % Subtype TCC generated (at line 106, column 16) for
      % {r | r1 < r AND r < r2}
      % expected type  nto_range
  nontrivial_open_range_TCC1: OBLIGATION
    FORALL (r1: T, (r2: {r | EXISTS t: r1 < t AND t < r})):
      (FORALL (lo, hi: ({r | r1 < r AND r < r2})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES
          member[T](r_1, {r | r1 < r AND r < r2}))
       AND
       (((NOT has_least?[T]
                  ({r | r1 < r AND r < r2},
                   restrict[[real, real], [T, T], boolean](<=)))
          OR has_non_least?({r | r1 < r AND r < r2}))
         AND
         ((NOT has_greatest?[T]
                   ({r | r1 < r AND r < r2},
                    restrict[[real, real], [T, T], boolean](<=)))
           OR has_non_greatest?({r | r1 < r AND r < r2})))
        AND nonempty?[T]({r | r1 < r AND r < r2});

  % Subtype TCC generated (at line 109, column 47) for  {r1 | r1 <= r}
      % expected type  oc_range
  open_closed_range_TCC2: OBLIGATION
    FORALL (r: (no_least)):
      (FORALL (lo, hi: ({r1 | r1 <= r})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES member[T](r_1, {r1 | r1 <= r}))
       AND
       ((NOT has_least?[T]
                 ({r1 | r1 <= r},
                  restrict[[real, real], [T, T], boolean](<=)))
         OR has_non_least?({r1 | r1 <= r}))
        AND
        has_greatest?[T]
            ({r1 | r1 <= r}, restrict[[real, real], [T, T], boolean](<=));

  % Subtype TCC generated (at line 110, column 50) for  {r1 | r <= r1}
      % expected type  co_range
  closed_open_range_TCC2: OBLIGATION
    FORALL (r: (no_greatest)):
      (FORALL (lo, hi: ({r1 | r <= r1})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES member[T](r_1, {r1 | r <= r1}))
       AND
       has_least?[T]
           ({r1 | r <= r1}, restrict[[real, real], [T, T], boolean](<=))
        AND
        ((NOT has_greatest?[T]
                  ({r1 | r <= r1},
                   restrict[[real, real], [T, T], boolean](<=)))
          OR has_non_greatest?({r1 | r <= r1}));

  % Subtype TCC generated (at line 111, column 47) for  {r1 | r1 < r}
      % expected type  nto_range
  left_open_range_TCC1: OBLIGATION
    FORALL (r: (no_least)):
      (FORALL (lo, hi: ({r1 | r1 < r})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES member[T](r_1, {r1 | r1 < r}))
       AND
       (((NOT has_least?[T]
                  ({r1 | r1 < r},
                   restrict[[real, real], [T, T], boolean](<=)))
          OR has_non_least?({r1 | r1 < r}))
         AND
         ((NOT has_greatest?[T]
                   ({r1 | r1 < r},
                    restrict[[real, real], [T, T], boolean](<=)))
           OR has_non_greatest?({r1 | r1 < r})))
        AND nonempty?[T]({r1 | r1 < r});

  % Subtype TCC generated (at line 112, column 50) for  {r1 | r < r1}
      % expected type  nto_range
  right_open_range_TCC1: OBLIGATION
    FORALL (r: (no_greatest)):
      (FORALL (lo, hi: ({r1 | r < r1})), (r_1: T):
         lo <= r_1 AND r_1 <= hi IMPLIES member[T](r_1, {r1 | r < r1}))
       AND
       (((NOT has_least?[T]
                  ({r1 | r < r1},
                   restrict[[real, real], [T, T], boolean](<=)))
          OR has_non_least?({r1 | r < r1}))
         AND
         ((NOT has_greatest?[T]
                   ({r1 | r < r1},
                    restrict[[real, real], [T, T], boolean](<=)))
           OR has_non_greatest?({r1 | r < r1})))
        AND nonempty?[T]({r1 | r < r1});


body:
  %-------------------------------------------------------------------------
  %
  %  The range theory, specialized for ranges of real numbers.
  %
  %  For PVS version 3.2.  February 9, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: finite_sets[real], orders[real], relations[real], sets[real]
  %  finite_sets: finite_sets_inductions, finite_sets_minmax
  %  orders: bounded_orders[real], minmax_orders[real], numbers_infinite,
  %    range[real], range_real, relations_extra[real]
  %
  %-------------------------------------------------------------------------
  range_real: THEORY
  BEGIN

    IMPORTING range[real], numbers_infinite

    r: VAR real

    real_no_minimum: JUDGEMENT real SUBTYPE_OF (no_least)

    real_no_maximum: JUDGEMENT real SUBTYPE_OF (no_greatest)

    ntc_range_infinite: JUDGEMENT ntc_range SUBTYPE_OF infinite_set[real]
    nto_range_infinite: JUDGEMENT nto_range SUBTYPE_OF infinite_set[real]

  END range_real

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 24, column 29) for  x
      % expected type  (no_least)
  real_no_minimum: OBLIGATION FORALL (x: real): no_least[real](x);

  % Judgement subtype TCC generated (at line 26, column 29) for  x
      % expected type  (no_greatest)
  real_no_maximum: OBLIGATION FORALL (x: real): no_greatest[real](x);

  % Judgement subtype TCC generated (at line 28, column 32) for  x
      % expected type  infinite_set[real]
  ntc_range_infinite: OBLIGATION
    FORALL (x: ntc_range): NOT is_finite[real](x);

  % Judgement subtype TCC generated (at line 29, column 32) for  x
      % expected type  infinite_set[real]
  nto_range_infinite: OBLIGATION
    FORALL (x: nto_range): NOT is_finite[real](x);


body:
  % non-empty sets of reals that are bounded from above or below.
  % These are exactly the sets that have least upper (greatest lower) bounds.
  %
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Dec 2004
  %
  % non_empty_finite_bounded_above and non_empty_finite_bounded_below added
  % 13 Jan 2005 by Jerry James (james@acm.org), University of Kansas

  non_empty_bounded_sets[T: TYPE FROM real]: THEORY

  BEGIN

    IMPORTING total_lattices[T, <=]

    non_empty_bounded_above?(S: set[T]): bool =
      nonempty?[T](S) & bounded_above?[T](<=)(S)

    non_empty_bounded_below?(S: set[T]): bool =
      nonempty?[T](S) & bounded_below?[T](<=)(S)

    non_empty_bounded_above_is_nonempty: JUDGEMENT
      (non_empty_bounded_above?) SUBTYPE_OF (nonempty?[T])

    non_empty_bounded_above_is_bounded_above: JUDGEMENT
      (non_empty_bounded_above?) SUBTYPE_OF (bounded_above?[T](<=))

    non_empty_bounded_below_is_nonempty: JUDGEMENT
      (non_empty_bounded_below?) SUBTYPE_OF (nonempty?[T])

    non_empty_bounded_below_is_bounded_below: JUDGEMENT
      (non_empty_bounded_below?) SUBTYPE_OF (bounded_below?[T](<=))

    non_empty_finite_bounded_above: JUDGEMENT
      non_empty_finite_set[T] SUBTYPE_OF (non_empty_bounded_above?)

    non_empty_finite_bounded_below: JUDGEMENT
      non_empty_finite_set[T] SUBTYPE_OF (non_empty_bounded_below?)

  END non_empty_bounded_sets

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 23, column 4) for  x
      % expected type  (nonempty?[T])
  non_empty_bounded_above_is_nonempty: OBLIGATION
    FORALL (x: (non_empty_bounded_above?)): nonempty?[T](x);

  % Judgement subtype TCC generated (at line 26, column 4) for  x
      % expected type  (LAMBDA (S: set[T]):
                     %    bounded_above?(S,
                     %                   restrict
                     %                   [[real, real], [T, T], boolean]
                     %                   (<=)))
  non_empty_bounded_above_is_bounded_above: OBLIGATION
    FORALL (x: (non_empty_bounded_above?)):
      bounded_above?[T](x, restrict[[real, real], [T, T], boolean](<=));

  % Judgement subtype TCC generated (at line 29, column 4) for  x
      % expected type  (nonempty?[T])
  non_empty_bounded_below_is_nonempty: OBLIGATION
    FORALL (x: (non_empty_bounded_below?)): nonempty?[T](x);

  % Judgement subtype TCC generated (at line 32, column 4) for  x
      % expected type  (LAMBDA (S: set[T]):
                     %    bounded_below?(S,
                     %                   restrict
                     %                   [[real, real], [T, T], boolean]
                     %                   (<=)))
  non_empty_bounded_below_is_bounded_below: OBLIGATION
    FORALL (x: (non_empty_bounded_below?)):
      bounded_below?[T](x, restrict[[real, real], [T, T], boolean](<=));

  % Judgement subtype TCC generated (at line 35, column 4) for  x
      % expected type  (non_empty_bounded_above?)
  non_empty_finite_bounded_above: OBLIGATION
    FORALL (x: non_empty_finite_set[T]): non_empty_bounded_above?(x);

  % Judgement subtype TCC generated (at line 38, column 4) for  x
      % expected type  (non_empty_bounded_below?)
  non_empty_finite_bounded_below: OBLIGATION
    FORALL (x: non_empty_finite_set[T]): non_empty_bounded_below?(x);


body:
  % every above (below) bounded, non-empty set of integers has a greatest
  % (least) element. This also holds for any subtype T of the integers.
  %
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: 2003/04
  %
  % remove_greatest, remove_greatest_monotone, intersection_greatest, and
  % intersection_least added 13 Jan 2005 by Jerry James (jamesj@acm.org),
  % University of Kansas

  bounded_integers[T: TYPE FROM int]: THEORY

  BEGIN

    IMPORTING
      non_empty_bounded_sets[T]

    Su, Su1, Su2: VAR (non_empty_bounded_above?)
    Sl, Sl1, Sl2: VAR (non_empty_bounded_below?)
    i, j: VAR T
    S: VAR set[T]
    c: VAR nat

    non_empty_bounded_above_has_greatest_lem: LEMMA
      S(i) & upper_bound?[T](j, S, <=) & c = j - i => has_greatest?(S, <=)

    non_empty_bounded_above_has_greatest: JUDGEMENT
      (non_empty_bounded_above?) SUBTYPE_OF (has_greatest?(<=))

    non_empty_bounded_below_has_least_lem: LEMMA
      S(i) & lower_bound?[T](j, S, <=) & c = i - j => has_least?(S, <=)

    non_empty_bounded_below_has_least: JUDGEMENT
      (non_empty_bounded_below?) SUBTYPE_OF (has_least?(<=))

    remove_least: LEMMA
      nonempty?(remove(least[T](restrict[[real, real], [T, T], bool](<=))(Sl),
                       Sl)) =>
        least[T](restrict[[real, real], [T, T], bool](<=))(Sl) <
        least[T](restrict[[real, real], [T, T], bool](<=))(
          remove(least[T](restrict[[real, real], [T, T], bool](<=))(Sl), Sl))

    remove_least_monotone: LEMMA
      subset?(Sl1, Sl2) =>
      subset?(
        remove(least[T](restrict[[real, real], [T, T], bool](<=))(Sl1), Sl1),
        remove(least[T](restrict[[real, real], [T, T], bool](<=))(Sl2), Sl2))

    remove_greatest: LEMMA
      nonempty?(remove(greatest[T](restrict[[real, real], [T, T], bool](<=))(Su),
                       Su)) =>
        greatest[T](restrict[[real, real], [T, T], bool](<=))(
          remove(greatest[T](restrict[[real, real], [T, T], bool](<=))(Su), Su))
        < greatest[T](restrict[[real, real], [T, T], bool](<=))(Su)

    remove_greatest_monotone: LEMMA
      subset?(Su1, Su2) =>
      subset?(
        remove(greatest[T](restrict[[real, real], [T, T], bool](<=))(Su1), Su1),
        remove(greatest[T](restrict[[real, real], [T, T], bool](<=))(Su2), Su2))

    intersection_greatest: LEMMA
      disjoint?(Su1, Su2) OR has_greatest?(intersection(Su1, Su2), <=)

    intersection_least: LEMMA
      disjoint?(Sl1, Sl2) OR has_least?(intersection(Sl1, Sl2), <=)

  END bounded_integers

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 28, column 4) for  x
      % expected type  (LAMBDA (S: set[T]):
                     %    has_greatest?(S,
                     %                  restrict
                     %                  [[real, real], [T, T], boolean]
                     %                  (<=)))
  non_empty_bounded_above_has_greatest: OBLIGATION
    FORALL (x: (non_empty_bounded_above?)):
      has_greatest?[T](x, restrict[[real, real], [T, T], boolean](<=));

  % Judgement subtype TCC generated (at line 34, column 4) for  x
      % expected type  (LAMBDA (S: set[T]):
                     %    has_least?(S,
                     %               restrict[[real, real], [T, T], boolean]
                     %                   (<=)))
  non_empty_bounded_below_has_least: OBLIGATION
    FORALL (x: (non_empty_bounded_below?)):
      has_least?[T](x, restrict[[real, real], [T, T], boolean](<=));

  % Subtype TCC generated (at line 41, column 8) for
      % remove(least[T](restrict[[real, real], [T, T], bool](<=))(Sl), Sl)
      % expected type  S:
                     %   (LAMBDA (S: set[T]):
                     %      has_least?(S,
                     %                 restrict[[real, real], [T, T], bool]
                     %                 (<=)))
  remove_least_TCC1: OBLIGATION
    FORALL (Sl: (non_empty_bounded_below?)):
      nonempty?(remove(least[T]
                           (restrict[[real, real], [T, T], bool](<=))(Sl),
                       Sl))
       IMPLIES
       has_least?[T]
           (remove[T]
                (least[T](restrict[[real, real], [T, T], bool](<=))(Sl), Sl),
            restrict[[real, real], [T, T], bool](<=));

  % Subtype TCC generated (at line 53, column 8) for
      % remove(greatest[T](restrict[[real, real], [T, T], bool](<=))(Su), Su)
      % expected type  S:
                     %   (LAMBDA (S: set[T]):
                     %      has_greatest?(S,
                     %                    restrict[[real, real], [T, T], bool]
                     %                    (<=)))
  remove_greatest_TCC1: OBLIGATION
    FORALL (Su: (non_empty_bounded_above?)):
      nonempty?(remove(greatest[T]
                           (restrict[[real, real], [T, T], bool](<=))(Su),
                       Su))
       IMPLIES
       has_greatest?[T]
           (remove[T]
                (greatest[T](restrict[[real, real], [T, T], bool](<=))(Su),
                 Su),
            restrict[[real, real], [T, T], bool](<=));


body:
  % every nonempty set of nats has a least element.
  % This also holds for any subtype T of the integers.
  %
  % Author: Jerry James (jamesj@acm.org), University of Kansas
  % Date: 13 Jan 2005

  bounded_nats[T: TYPE FROM nat]: THEORY

  BEGIN

    IMPORTING bounded_integers[T]

    every_nonempty_set_has_least: JUDGEMENT
      (nonempty?[T]) SUBTYPE_OF (has_least?(<=))

  END bounded_nats

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 14, column 4) for  x
      % expected type  (LAMBDA (S: set[T]):
                     %    has_least?(S,
                     %               restrict[[real, real], [T, T], boolean]
                     %                   (<=)))
  every_nonempty_set_has_least: OBLIGATION
    FORALL (x: (nonempty?[T])):
      has_least?[T](x, restrict[[real, real], [T, T], boolean](<=));


body:
  %-------------------------------------------------------------------------
  %
  %  Specializations of the ordered_subset theory to sets of natural numbers.
  %
  %  For PVS version 3.2.  February 8, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: finite_sets[nat], infinite_sets_def[nat], orders[nat],
  %    real_props, relation_props2[nat,nat,nat,nat], relations[nat],
  %    restrict_order_props[real,nat], sets[nat]
  %  finite_sets: finite_sets_inductions, finite_sets_minmax
  %  orders: bounded_integers[nat], bounded_nats[nat], bounded_orders[nat],
  %    bounded_sets[nat,<=], closure_ops[nat], indexed_sets_extra,
  %    lattices[nat,<=], lower_semilattices[nat,<=], minmax_orders[nat],
  %    non_empty_bounded_sets[nat], ordered_nat, ordered_subset[nat],
  %    relation_iterate[nat], relations_extra[nat], total_lattices[nat,<=],
  %    upper_semilattices[nat,<=]
  %
  %-------------------------------------------------------------------------
  ordered_nat: THEORY
   BEGIN

    IMPORTING infinite_sets_def[nat], restrict_order_props[real, nat]
    IMPORTING real_props, ordered_subset[nat]
    IMPORTING bounded_nats[nat] % Proofs only

    n: VAR nat
    pre, pre1, pre2: VAR (prefix?(<=))
    suf: VAR (suffix?(<=))

    % A convenient shorthand
    lesseq: MACRO pred[[nat, nat]] =
        restrict[[real, real], [nat, nat], boolean](<=)

    % Attempting to use the ordered_subset definitions directly in the
    % judgements below causes PVS 3.2 to complain that the variable 'lesseq'
    % is undeclared.  Changing to 'reals.<=' causes the parser to choke on
    % the '.'.
    upto(n): MACRO (prefix?(lesseq)) = upto(n, lesseq)
    below(n): MACRO (prefix?(lesseq)) = below(n, lesseq)
    above(n): MACRO (suffix?(lesseq)) = above(n, lesseq)
    upfrom(n): MACRO (suffix?(lesseq)) = upfrom(n, lesseq)

    upto_has_greatest: JUDGEMENT upto(n) HAS_TYPE (has_greatest?(lesseq))
    above_has_least: JUDGEMENT above(n) HAS_TYPE (has_least?(lesseq))
    upfrom_has_least: JUDGEMENT upfrom(n) HAS_TYPE (has_least?(lesseq))

    nonzero_below_greatest: LEMMA
      FORALL n:
        n > 0 IMPLIES
         has_greatest?(below(n), lesseq) AND
          greatest(lesseq)(below(n)) = n - 1

    upto_greatest: LEMMA FORALL n: greatest(lesseq)(upto(n)) = n
    above_least: LEMMA FORALL n: least(lesseq)(above(n)) = n + 1
    upfrom_least: LEMMA FORALL n: least(lesseq)(upfrom(n)) = n

    below_prelude: LEMMA
      FORALL n:
        below(n) =
         extend[nat, naturalnumbers.below(n), bool, FALSE]
             (fullset[naturalnumbers.below(n)])

    upto_prelude: LEMMA
      FORALL n:
        upto(n) =
         extend[nat, naturalnumbers.upto(n), bool, FALSE]
             (fullset[naturalnumbers.upto(n)])

    prefix_finite: THEOREM FORALL pre: is_finite(pre) OR full?(pre)

    prefix_below: THEOREM
      FORALL pre: is_finite(pre) IMPLIES pre = below(card(pre))

    prefix_upto: THEOREM
      FORALL pre:
        is_finite(pre) IMPLIES empty?(pre) OR pre = upto(card(pre) - 1)

    below_is_finite: JUDGEMENT below(n) HAS_TYPE finite_set
    upto_is_finite: JUDGEMENT upto(n) HAS_TYPE finite_set

    below_card: LEMMA FORALL n: card(below(n)) = n
    upto_card: LEMMA FORALL n: card(upto(n)) = 1 + n

    suffix_empty: THEOREM FORALL suf: is_finite(suf) IMPLIES empty?(suf)

    suffix_upfrom: THEOREM
      FORALL suf: empty?(suf) OR (EXISTS n: suf = upfrom(n))

    suffix_above: THEOREM
      FORALL suf: empty?(suf) OR full?(suf) OR (EXISTS n: suf = above(n))

    unrelated_empty: THEOREM FORALL n: empty?(unrelated(n, lesseq))

    prefix_finite_full: LEMMA
      FORALL pre1, pre2:
        is_finite(pre1) AND full?(pre2) IMPLIES
         (FORALL (f: [(pre1) -> (pre2)]): NOT surjective?(f))

    prefix_bijective: THEOREM
      FORALL pre1, pre2:
        (EXISTS (f: [(pre1) -> (pre2)]): bijective?(f)) IMPLIES pre1 = pre2

   END ordered_nat

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 42, column 37) for
      % upto(n, restrict[[real, real], [nat, nat], boolean](<=))
      % expected type  (LAMBDA (S: set[nat]):
                     %    has_greatest?(S,
                     %                  restrict
                     %                  [[real, real], [nat, nat], boolean]
                     %                  (<=)))
  upto_has_greatest: OBLIGATION
    FORALL (n):
      has_greatest?[nat]
          (upto[nat](n, restrict[[real, real], [nat, nat], boolean](<=)),
           restrict[[real, real], [nat, nat], boolean](<=));

  % Judgement subtype TCC generated (at line 44, column 38) for
      % above(n, restrict[[real, real], [nat, nat], boolean](<=))
      % expected type  (LAMBDA (S: set[nat]):
                     %    has_least?(S,
                     %               restrict
                     %                   [[real, real], [nat, nat], boolean]
                     %                   (<=)))
  above_has_least: OBLIGATION
    FORALL (n):
      has_least?[nat]
          (above[nat](n, restrict[[real, real], [nat, nat], boolean](<=)),
           restrict[[real, real], [nat, nat], boolean](<=));

  % Judgement subtype TCC generated (at line 45, column 39) for
      % upfrom(n, restrict[[real, real], [nat, nat], boolean](<=))
      % expected type  (LAMBDA (S: set[nat]):
                     %    has_least?(S,
                     %               restrict
                     %                   [[real, real], [nat, nat], boolean]
                     %                   (<=)))
  upfrom_has_least: OBLIGATION
    FORALL (n):
      has_least?[nat]
          (upfrom[nat](n, restrict[[real, real], [nat, nat], boolean](<=)),
           restrict[[real, real], [nat, nat], boolean](<=));

  % Subtype TCC generated (at line 80, column 55) for  card(pre) - 1
      % expected type  nat
  prefix_upto_TCC1: OBLIGATION
    FORALL (pre):
      NOT empty?(pre) AND is_finite(pre) IMPLIES card[nat](pre) - 1 >= 0;

  % Judgement subtype TCC generated (at line 43, column 38) for
      % below(n, restrict[[real, real], [nat, nat], boolean](<=))
      % expected type  finite_set[nat]
  below_is_finite: OBLIGATION
    FORALL (n):
      is_finite[nat]
          (below[nat](n, restrict[[real, real], [nat, nat], boolean](<=)));

  % Judgement subtype TCC generated (at line 42, column 37) for
      % upto(n, restrict[[real, real], [nat, nat], boolean](<=))
      % expected type  finite_set[nat]
  upto_is_finite: OBLIGATION
    FORALL (n):
      is_finite[nat]
          (upto[nat](n, restrict[[real, real], [nat, nat], boolean](<=)));


body:
  %-------------------------------------------------------------------------
  %
  %  Specialization of the ordered_subset theory to sets of integers.
  %
  %  For PVS version 3.2.  January 31, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: finite_sets[int], infinite_sets_def[int], orders[int],
  %    real_props, relation_props2[int, int, int, int], relations[int],
  %    restrict_order_props[real, int], sets[int]
  %  finite_sets: finite_sets_inductions, finite_sets_minmax
  %  orders: bounded_orders[int], closure_ops[int], indexed_sets_extra,
  %    minmax_orders[int], ordered_int, ordered_subset[int],
  %    relation_iterate[int], relations_extra[int]
  %
  %-------------------------------------------------------------------------
  ordered_int: THEORY
   BEGIN

    IMPORTING infinite_sets_def[int], restrict_order_props[real, int]
    IMPORTING real_props, minmax_orders[int], ordered_subset[int]

    i: VAR int
    pre: VAR (prefix?(<=))
    suf: VAR (suffix?(<=))

    % Attempting to use the ordered_subset definitions directly in the
    % judgements below causes PVS 3.2 to complain that the variable '<=' is
    % undeclared.  Changing to 'reals.<=' causes the parser to choke on the '.'.
    upto(i): MACRO (prefix?(<=)) = upto(i, <=)
    below(i): MACRO (prefix?(<=)) = below(i, <=)
    above(i): MACRO (suffix?(<=)) = above(i, <=)
    upfrom(i): MACRO (suffix?(<=)) = upfrom(i, <=)

    upto_has_greatest: JUDGEMENT upto(i) HAS_TYPE (has_greatest?(<=))
    below_has_greatest: JUDGEMENT below(i) HAS_TYPE (has_greatest?(<=))
    above_has_least: JUDGEMENT above(i) HAS_TYPE (has_least?(<=))
    upfrom_has_least: JUDGEMENT upfrom(i) HAS_TYPE (has_least?(<=))

    prefix_empty: THEOREM FORALL pre: is_finite(pre) IMPLIES empty?(pre)

    prefix_below: THEOREM
      FORALL pre: empty?(pre) OR full?(pre) OR (EXISTS i: pre = below(i))

    prefix_upto: THEOREM
      FORALL pre: empty?(pre) OR full?(pre) OR (EXISTS i: pre = upto(i))

    suffix_empty: THEOREM FORALL suf: is_finite(suf) IMPLIES empty?(suf)

    suffix_upfrom: THEOREM
      FORALL suf: empty?(suf) OR full?(suf) OR (EXISTS i: suf = upfrom(i))

    suffix_above: THEOREM
      FORALL suf: empty?(suf) OR full?(suf) OR (EXISTS i: suf = above(i))

    unrelated_empty: THEOREM FORALL i: empty?(unrelated(i, <=))

   END ordered_int

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 33, column 33) for
      % upto(i, restrict[[real, real], [int, int], boolean](<=))
      % expected type  (LAMBDA (S: set[int]):
                     %    has_greatest?(S,
                     %                  restrict
                     %                  [[real, real], [int, int], boolean]
                     %                  (<=)))
  upto_has_greatest: OBLIGATION
    FORALL (i):
      has_greatest?[int]
          (upto[int](i, restrict[[real, real], [int, int], boolean](<=)),
           restrict[[real, real], [int, int], boolean](<=));

  % Judgement subtype TCC generated (at line 34, column 34) for
      % below(i, restrict[[real, real], [int, int], boolean](<=))
      % expected type  (LAMBDA (S: set[int]):
                     %    has_greatest?(S,
                     %                  restrict
                     %                  [[real, real], [int, int], boolean]
                     %                  (<=)))
  below_has_greatest: OBLIGATION
    FORALL (i):
      has_greatest?[int]
          (below[int](i, restrict[[real, real], [int, int], boolean](<=)),
           restrict[[real, real], [int, int], boolean](<=));

  % Judgement subtype TCC generated (at line 35, column 34) for
      % above(i, restrict[[real, real], [int, int], boolean](<=))
      % expected type  (LAMBDA (S: set[int]):
                     %    has_least?(S,
                     %               restrict
                     %                   [[real, real], [int, int], boolean]
                     %                   (<=)))
  above_has_least: OBLIGATION
    FORALL (i):
      has_least?[int]
          (above[int](i, restrict[[real, real], [int, int], boolean](<=)),
           restrict[[real, real], [int, int], boolean](<=));

  % Judgement subtype TCC generated (at line 36, column 35) for
      % upfrom(i, restrict[[real, real], [int, int], boolean](<=))
      % expected type  (LAMBDA (S: set[int]):
                     %    has_least?(S,
                     %               restrict
                     %                   [[real, real], [int, int], boolean]
                     %                   (<=)))
  upfrom_has_least: OBLIGATION
    FORALL (i):
      has_least?[int]
          (upfrom[int](i, restrict[[real, real], [int, int], boolean](<=)),
           restrict[[real, real], [int, int], boolean](<=));


body:
  %-------------------------------------------------------------------------
  %
  %  "Stronger" and "weaker" orders.  Given two relations on T, rel1 and
  %  rel2, if strict_subset?(rel1, rel2), then we say that rel1 is
  %  weaker than rel2, and that rel2 is stronger than rel1.  If
  %  subset?(rel1, rel2), then rel1 is weaker than or equal to rel2, and
  %  rel2 is stronger than or equal to rel1.
  %
  %  For PVS version 3.2.  January 14, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  orders: order_strength[T]
  %
  %-------------------------------------------------------------------------
  order_strength[T: TYPE]: THEORY
   BEGIN

    t1, t2: VAR T
    ord1, ord2: VAR pred[[T, T]]

    % Stronger orders: if ord1 is stronger than ord2, then ord1 orders every
    % pair of elements that ord2 orders
    stronger_eq?(ord1, ord2): MACRO bool = subset?(ord2, ord1)
    stronger_eq?(ord2)(ord1): MACRO bool = subset?(ord2, ord1)
    stronger?(ord1, ord2): MACRO bool = strict_subset?(ord2, ord1)
    stronger?(ord2)(ord1): MACRO bool = strict_subset?(ord2, ord1)

    % Weaker orders: if ord1 is weaker than ord2, then ord2 orders every
    % pair of elements that ord1 orders
    weaker_eq?(ord1, ord2): MACRO bool = subset?(ord1, ord2)
    weaker_eq?(ord2)(ord1): MACRO bool = subset?(ord1, ord2)
    weaker?(ord1, ord2): MACRO bool = strict_subset?(ord1, ord2)
    weaker?(ord2)(ord1): MACRO bool = strict_subset?(ord1, ord2)


    % ==========================================================================
    % Properties preserved by stronger/weaker orders
    % ==========================================================================

    stronger_reflexive: THEOREM
      FORALL ord1, ord2:
        stronger_eq?(ord1, ord2) AND reflexive?(ord2) => reflexive?(ord1)

    weaker_irreflexive: THEOREM
      FORALL ord1, ord2:
        weaker_eq?(ord1, ord2) AND irreflexive?(ord2) => irreflexive?(ord1)

    weaker_antisymmetric: THEOREM
      FORALL ord1, ord2:
        weaker_eq?(ord1, ord2) AND antisymmetric?(ord2) =>
         antisymmetric?(ord1)

   END order_strength


body:
  %-------------------------------------------------------------------------
  %
  %  Kuratowski's lemma: there exists a maximal chain.  This is equivalent
  %  to Zorn's lemma and the Axiom of Choice.
  %
  %  For PVS version 3.2.  January 17, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[chain[T,<=]], orders[T], sets[T]
  %  orders: chain[T,<=], kuratowski[T,<=]
  %
  %-------------------------------------------------------------------------
  kuratowski[T: TYPE, <=: (partial_order?[T])]: THEORY

   % Hide the imports used only in the proof
   EXPORTING ALL WITH orders[T], sets[T], orders[chain[T, <=]], chain[T, <=]

   BEGIN

    IMPORTING chain_chain[T, <=], zorn[subchain, chain_incl]

    kuratowski: THEOREM EXISTS (ch: chain[T, <=]): maximal_chain?[T, <=](ch)

   END kuratowski


body:
  %-------------------------------------------------------------------------
  %
  %  Isomorphisms are transitive.
  %
  %  For PVS version 3.2.  January 18, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[T1], orders[T2], orders[T3], relations[T1],
  %    relations[T2], relations[T3]
  %  orders: isomorphism[T1,T2], isomorphism[T1,T3], isomorphism[T2,T3],
  %    isomorphism_transitive[T1,T2,T3], relations_extra[T1],
  %    relations_extra[T2], relations_extra[T3]
  %
  %-------------------------------------------------------------------------
  isomorphism_transitive[T1: TYPE, T2: TYPE, T3: TYPE]: THEORY
   BEGIN

    IMPORTING isomorphism[T1, T2], isomorphism[T2, T3], isomorphism[T1, T3]

    rel1: VAR pred[[T1, T1]]
    rel2: VAR pred[[T2, T2]]
    rel3: VAR pred[[T3, T3]]

    isomorphism_transitive: THEOREM
      FORALL rel1, rel2, rel3:
        isomorphic?(rel1, rel2) AND isomorphic?(rel2, rel3) =>
         isomorphic?(rel1, rel3)

   END isomorphism_transitive


body:
  %-------------------------------------------------------------------------
  %
  %  Isomorphisms are symmetric.
  %
  %  For PVS version 3.2.  January 18, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[T1], orders[T2], relations[T1], relations[T2]
  %  orders: isomorphism[T1,T2], isomorphism[T2,T1],
  %    isomorphism_symmetric[T1,T2], relations_extra[T1], relations_extra[T2]
  %
  %-------------------------------------------------------------------------
  isomorphism_symmetric[T1: TYPE, T2: TYPE]: THEORY

  EXPORTING ALL WITH orders[T1], orders[T2], relations[T1], relations[T2],
  		   isomorphism[T1, T2], isomorphism[T2, T1],
  		   relations_extra[T1], relations_extra[T2]

   BEGIN

    IMPORTING function_inverse_def[T1, T2]  % Proofs only
    IMPORTING function_inverse_def[T2, T1]  % Proofs only
    IMPORTING isomorphism[T1, T2], isomorphism[T2, T1]

    rel1: VAR pred[[T1, T1]]
    rel2: VAR pred[[T2, T2]]

    isomorphism_symmetric: THEOREM
      FORALL rel1, rel2: isomorphic?(rel1, rel2) IFF isomorphic?(rel2, rel1)

   END isomorphism_symmetric


body:
  %-------------------------------------------------------------------------
  %
  %  Equivalence classes of automorphisms.
  %
  %  For PVS version 3.2.  November 4, 2004
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[T], relations[pred[[T, T]]], relations[T]
  %  orders: isomorphism[T,T], isomorphism_equivalence[T], relations_extra[T]
  %
  %-------------------------------------------------------------------------
  isomorphism_equivalence[T: TYPE]: THEORY

  EXPORTING ALL WITH orders[T], relations[pred[[T, T]]], relations[T],
  		   isomorphism[T, T], relations_extra[T]

   BEGIN

    IMPORTING function_inverse_def[T, T]      % Proofs only
    IMPORTING relations[pred[[T, T]]], isomorphism[T, T]

    isomorphism_reflexive: THEOREM reflexive?(isomorphic?)

    isomorphism_symmetric: THEOREM symmetric?(isomorphic?)

    isomorphism_transitive: THEOREM transitive?(isomorphic?)

    isomorphism_equivalence: JUDGEMENT
      isomorphic? HAS_TYPE equivalence[pred[[T, T]]]

   END isomorphism_equivalence

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 32, column 4) for  isomorphic?
      % expected type  equivalence[pred[[T, T]]]
  isomorphism_equivalence: OBLIGATION
    equivalence?[pred[[T, T]]](isomorphic?[T, T]);


body:
  %-------------------------------------------------------------------------
  %
  %  The converse of Zorn's lemma: if every chain has a lower bound, then
  %  the set has a minimal element.
  %
  %  For PVS version 3.2.  January 17, 2005
  %  ---------------------------------------------------------------------
  %      Author: Jerry James (jamesj@acm.org), University of Kansas
  %
  %  EXPORTS
  %  -------
  %  prelude: orders[T], relations[T], sets[T]
  %  orders: bounded_orders[T], chain[T,<=], converse_zorn[T,<=],
  %    minmax_orders[T], relations_extra[T]
  %
  %-------------------------------------------------------------------------
  converse_zorn[T: TYPE, <=: (partial_order?[T])]: THEORY

   EXPORTING ALL WITH orders[T], relations[T], sets[T], bounded_orders[T],
             chain[T, <=], minmax_orders[T], relations_extra[T]

   BEGIN

    IMPORTING minmax_orders[T], chain[T, <=]
    IMPORTING relation_converse_props[T], zorn[T, converse(<=)] % Proof only

    converse_zorn: THEOREM
      (FORALL (ch: chain[T, <=]): bounded_below?[T](ch, <=)) =>
       (EXISTS (t: T): minimal?[T](t, fullset[T], <=))

   END converse_zorn


body:
  % infinite ascending and descending sequences and their subsequences
  %
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Dec 2004

  monotone_sequences[T: TYPE]: THEORY

  BEGIN

    IMPORTING closure_ops[T]

    n: VAR nat
    x, y: VAR T
    rel: VAR pred[[T, T]]
    seq: VAR sequence[T]
    lt: VAR (transitive?[T])
    asc: VAR (preserves[nat, nat](<, <))

    % these definitions do not require rel to be a partial order

    ascending?(rel)(seq): bool =
      FORALL n: rel(seq(n), seq(n + 1))

    descending?(rel)(seq): bool =
      FORALL n: rel(seq(n + 1), seq(n))

    reflexive_closure_ascending: LEMMA
      FORALL (seq: (ascending?(rel))): ascending?(reflexive_closure(rel))(seq)

    reflexive_closure_descending: LEMMA
      FORALL (seq: (descending?(rel))): descending?(reflexive_closure(rel))(seq)

    ascending_lem: LEMMA
      FORALL (seq: (ascending?(lt))): preserves(seq, <, lt)

    descending_lem: LEMMA
      FORALL (seq: (descending?(lt))): preserves(seq, <, converse(lt))

    % subsequences
    ascending_subsequence: THEOREM
      FORALL (seq: (ascending?(lt))): ascending?(lt)(seq o asc)

    descending_subsequence: THEOREM
      FORALL (seq: (descending?(lt))): descending?(lt)(seq o asc)

  END monotone_sequences


body:
  % a characterization of well-foundedness by the absence of infinitely
  % descending sequences; well-founded orders.
  %
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Dec 2004 / Jan 2005

  well_foundedness[T: TYPE]: THEORY

  BEGIN

    IMPORTING orders[T], monotone_sequences[T], skolemization, closure_ops[T]

    n: VAR nat
    x, y: VAR T
    rel: VAR pred[[T, T]]
    seq: VAR sequence[T]

    no_infinite_descending_sequence: THEOREM
      well_founded?(rel) <=> empty?[sequence[T]](descending?(rel))

    well_founded_is_irreflexive: JUDGEMENT
      (well_founded?) SUBTYPE_OF (irreflexive?[T])

    well_founded_order?(rel): bool =
      well_founded?[T](rel) & transitive?[T](rel)

    well_order_is_well_founded_order: JUDGEMENT
      (well_ordered?[T]) SUBTYPE_OF (well_founded_order?)

    well_founded_order_is_well_founded: JUDGEMENT
      (well_founded_order?) SUBTYPE_OF (well_founded?)

    well_founded_order_is_strict_order: JUDGEMENT
      (well_founded_order?) SUBTYPE_OF (strict_order?)

    transitive_closure_preserves_well_foundedness: JUDGEMENT
      transitive_closure(rel: (well_founded?[T])) HAS_TYPE (well_founded_order?)

  END well_foundedness

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 22, column 4) for  x
      % expected type  (irreflexive?[T])
  well_founded_is_irreflexive: OBLIGATION
    FORALL (x: (well_founded?)): irreflexive?[T](x);

  % Judgement subtype TCC generated (at line 28, column 4) for  x
      % expected type  (well_founded_order?)
  well_order_is_well_founded_order: OBLIGATION
    FORALL (x: (well_ordered?[T])): well_founded_order?(x);

  % Judgement subtype TCC generated (at line 31, column 4) for  x
      % expected type  (well_founded?)
  well_founded_order_is_well_founded: OBLIGATION
    FORALL (x: (well_founded_order?)): well_founded?[T](x);

  % Judgement subtype TCC generated (at line 34, column 4) for  x
      % expected type  (strict_order?)
  well_founded_order_is_strict_order: OBLIGATION
    FORALL (x: (well_founded_order?)): strict_order?[T](x);

  % Judgement subtype TCC generated (at line 37, column 4) for
      % transitive_closure(rel)
      % expected type  (well_founded_order?)
  transitive_closure_preserves_well_foundedness: OBLIGATION
    FORALL (rel: (well_founded?[T])):
      well_founded_order?(transitive_closure[T](rel));


body:
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Oct 2004

  complete_upper_semilattices[
    T: TYPE,
    (IMPORTING bounded_orders[T])
    <=: (complete_upper_semilattice?[T])
  ]: THEORY

  BEGIN

    IMPORTING upper_semilattices[T, <=]

    every_set_is_least_bounded_above: JUDGEMENT
      set[T] SUBTYPE_OF (least_bounded_above?(<=))

  END complete_upper_semilattices

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 15, column 4) for  x
      % expected type  (LAMBDA (S: set[T]): least_bounded_above?(S, <=))
  every_set_is_least_bounded_above: OBLIGATION
    FORALL (x: set[T]): least_bounded_above?[T](x, <=);


body:
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Oct 2004

  complete_lower_semilattices[
    T: TYPE,
    (IMPORTING bounded_orders[T])
    <=: (complete_lower_semilattice?[T])
  ]: THEORY

  BEGIN

    IMPORTING lower_semilattices[T, <=]

    every_set_is_greatest_bounded_below: JUDGEMENT
      set[T] SUBTYPE_OF (greatest_bounded_below?(<=))

  END complete_lower_semilattices

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 15, column 4) for  x
      % expected type  (LAMBDA (S: set[T]): greatest_bounded_below?(S, <=))
  every_set_is_greatest_bounded_below: OBLIGATION
    FORALL (x: set[T]): greatest_bounded_below?[T](x, <=);


body:
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Oct 2004

  complete_lattices[
    T: TYPE,
    (IMPORTING bounded_orders[T])
    <=: (complete_lattice?[T])
  ]: THEORY

  BEGIN

    IMPORTING
  %    bounded_sets[T, <=],
      complete_lower_semilattices[T, <=],
      complete_upper_semilattices[T, <=]

    every_set_is_tightly_bounded: JUDGEMENT
      set[T] SUBTYPE_OF (tightly_bounded?(<=))

  END complete_lattices

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 18, column 4) for  x
      % expected type  (LAMBDA (S: set[T]): tightly_bounded?(S, <=))
  every_set_is_tightly_bounded: OBLIGATION
    FORALL (x: set[T]): tightly_bounded?[T](x, <=);


body:
  % A partial order on R induces a partial order on functions that range in R,
  % called the pointwise order. The pointwise order preserves complete
  % lower semilattices, complete upper semilattices, and complete lattices.
  %
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Dec 2004

  pointwise_orders[
    D, R: TYPE
  ]: THEORY

  BEGIN

    IMPORTING bounded_orders, skolemization[D, R], closure_ops

    x: VAR D
    r, s: VAR R
    rr: VAR set[R]
    f, g: VAR [D -> R]
    ff: VAR set[[D -> R]]
    nff: VAR non_empty_finite_set[[D -> R]]
    rel: VAR pred[[R,R]]
    alt: VAR (antisymmetric?[R])

  % f is pointwise less than, or equal to, g if f(x) <= g(x) for all x.
    pointwise(rel)(f,g): bool = FORALL x: rel(f(x), g(x))

    strictly_pointwise(rel): pred[[[D -> R], [D -> R]]] =
      irreflexive_kernel(pointwise(reflexive_closure(rel)))

    pointwise_preserves_reflexive: JUDGEMENT
      pointwise(rel: (reflexive?[R])) HAS_TYPE (reflexive?[[D -> R]])

    pointwise_preserves_transitive: JUDGEMENT
      pointwise(rel: (transitive?[R])) HAS_TYPE (transitive?[[D -> R]])

    pointwise_preserves_preorder: JUDGEMENT
      pointwise(lt: (preorder?[R])) HAS_TYPE (preorder?[[D -> R]])

    pointwise_preserves_antisymmetric: JUDGEMENT
      pointwise(rel: (antisymmetric?[R])) HAS_TYPE (antisymmetric?[[D -> R]])

    pointwise_preserves_partial_order: JUDGEMENT
      pointwise(lt: (partial_order?[R])) HAS_TYPE (partial_order?[[D -> R]])

    % if nff is non-empty and finite, then so is every set of the form
    % {s | EXISTS f: nff(f) & s = f(x)} for any x
    finiteness_lemma: LEMMA
      nonempty?[R]({s | EXISTS f: nff(f) & s = f(x)}) AND
      is_finite[R]({s | EXISTS f: nff(f) & s = f(x)})

    least_upper_bound_pointwise: THEOREM
      least_upper_bound?[[D -> R]](f, ff, pointwise(rel)) IFF
      FORALL x:
        least_upper_bound?[R](f(x), {s | EXISTS f: ff(f) AND s = f(x)}, rel)

    least_bounded_above_pointwise: LEMMA
      least_bounded_above?[[D -> R]](ff, pointwise(rel)) IFF
      FORALL x:
        least_bounded_above?[R]({s | EXISTS f: ff(f) AND s = f(x)}, rel)

    pointwise_preserves_upper_semilattices: JUDGEMENT
      pointwise(lt: (upper_semilattice?[R])) HAS_TYPE
        (upper_semilattice?[[D -> R]])

    pointwise_preserves_complete_upper_semilattices: JUDGEMENT
      pointwise(lt: (complete_upper_semilattice?[R])) HAS_TYPE
        (complete_upper_semilattice?[[D -> R]])

    greatest_lower_bound_pointwise: LEMMA
      greatest_lower_bound?[[D -> R]](f, ff, pointwise(rel)) IFF
      FORALL x:
        greatest_lower_bound?[R](f(x), {s | EXISTS f: ff(f) & s = f(x)}, rel)

    greatest_bounded_below_pointwise: LEMMA
      greatest_bounded_below?(ff, pointwise(alt)) IFF
      (FORALL x:
        greatest_bounded_below?(alt)({s | EXISTS f: ff(f) & s = f(x)}))

    pointwise_preserves_lower_semilattices: JUDGEMENT
      pointwise(lt: (lower_semilattice?[R])) HAS_TYPE
        (lower_semilattice?[[D -> R]])

    pointwise_preserves_complete_lower_semilattices: JUDGEMENT
      pointwise(lt: (complete_lower_semilattice?[R])) HAS_TYPE
        (complete_lower_semilattice?[[D -> R]])

    pointwise_preserves_lattices: JUDGEMENT
      pointwise(lt: (lattice?[R])) HAS_TYPE (lattice?[[D -> R]])

    pointwise_preserves_complete_lattices: JUDGEMENT
      pointwise(lt: (complete_lattice?[R])) HAS_TYPE
        (complete_lattice?[[D -> R]])

    lub_pointwise_def: LEMMA
      (FORALL x:
        least_bounded_above?(alt)({s | EXISTS f: ff(f) & s = f(x)})) =>
      lub[[D -> R]](pointwise(alt))(ff) =
        LAMBDA x: lub[R](alt)({s | EXISTS f: ff(f) & s = f(x)})

    glb_pointwise_def: LEMMA
      (FORALL x:
        greatest_bounded_below?(alt)({s | EXISTS f: ff(f) & s = f(x)})) =>
      glb[[D -> R]](pointwise(alt))(ff) =
        LAMBDA x: glb[R](alt)({s | EXISTS f: ff(f) & s = f(x)})

  END pointwise_orders

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 32, column 4) for  pointwise(rel)
      % expected type  (reflexive?[[D -> R]])
  pointwise_preserves_reflexive: OBLIGATION
    FORALL (rel: (reflexive?[R])): reflexive?[[D -> R]](pointwise(rel));

  % Judgement subtype TCC generated (at line 35, column 4) for  pointwise(rel)
      % expected type  (transitive?[[D -> R]])
  pointwise_preserves_transitive: OBLIGATION
    FORALL (rel: (transitive?[R])): transitive?[[D -> R]](pointwise(rel));

  % Judgement subtype TCC generated (at line 38, column 4) for  pointwise(lt)
      % expected type  (preorder?[[D -> R]])
  pointwise_preserves_preorder: OBLIGATION
    FORALL (lt: (preorder?[R])): preorder?[[D -> R]](pointwise(lt));

  % Judgement subtype TCC generated (at line 41, column 4) for  pointwise(rel)
      % expected type  (antisymmetric?[[D -> R]])
  pointwise_preserves_antisymmetric: OBLIGATION
    FORALL (rel: (antisymmetric?[R])):
      antisymmetric?[[D -> R]](pointwise(rel));

  % Judgement subtype TCC generated (at line 44, column 4) for  pointwise(lt)
      % expected type  (partial_order?[[D -> R]])
  pointwise_preserves_partial_order: OBLIGATION
    FORALL (lt: (partial_order?[R])): partial_order?[[D -> R]](pointwise(lt));

  % Judgement subtype TCC generated (at line 63, column 4) for  pointwise(lt)
      % expected type  (upper_semilattice?[[D -> R]])
  pointwise_preserves_upper_semilattices: OBLIGATION
    FORALL (lt: (upper_semilattice?[R])):
      upper_semilattice?[[D -> R]](pointwise(lt));

  % Judgement subtype TCC generated (at line 67, column 4) for  pointwise(lt)
      % expected type  (complete_upper_semilattice?[[D -> R]])
  pointwise_preserves_complete_upper_semilattices: OBLIGATION
    FORALL (lt: (complete_upper_semilattice?[R])):
      complete_upper_semilattice?[[D -> R]](pointwise(lt));

  % Judgement subtype TCC generated (at line 81, column 4) for  pointwise(lt)
      % expected type  (lower_semilattice?[[D -> R]])
  pointwise_preserves_lower_semilattices: OBLIGATION
    FORALL (lt: (lower_semilattice?[R])):
      lower_semilattice?[[D -> R]](pointwise(lt));

  % Judgement subtype TCC generated (at line 85, column 4) for  pointwise(lt)
      % expected type  (complete_lower_semilattice?[[D -> R]])
  pointwise_preserves_complete_lower_semilattices: OBLIGATION
    FORALL (lt: (complete_lower_semilattice?[R])):
      complete_lower_semilattice?[[D -> R]](pointwise(lt));

  % Judgement subtype TCC generated (at line 89, column 4) for  pointwise(lt)
      % expected type  (lattice?[[D -> R]])
  pointwise_preserves_lattices: OBLIGATION
    FORALL (lt: (lattice?[R])): lattice?[[D -> R]](pointwise(lt));

  % Judgement subtype TCC generated (at line 92, column 4) for  pointwise(lt)
      % expected type  (complete_lattice?[[D -> R]])
  pointwise_preserves_complete_lattices: OBLIGATION
    FORALL (lt: (complete_lattice?[R])):
      complete_lattice?[[D -> R]](pointwise(lt));

  % Subtype TCC generated (at line 98, column 34) for  ff
      % expected type  S:
                     %   (LAMBDA (S: set[[D -> R]]):
                     %      least_bounded_above?(S, pointwise(alt)))
  lub_pointwise_def_TCC1: OBLIGATION
    FORALL (alt: (antisymmetric?[R]), ff: set[[D -> R]]):
      (FORALL x: least_bounded_above?({s | EXISTS f: ff(f) & s = f(x)}, alt))
       IMPLIES least_bounded_above?[[D -> R]](ff, pointwise(alt));

  % Subtype TCC generated (at line 99, column 28) for
      % {s | EXISTS f: ff(f) & s = f(x)}
      % expected type  S: (LAMBDA (S: set[R]): least_bounded_above?(S, alt))
  lub_pointwise_def_TCC2: OBLIGATION
    FORALL (alt: (antisymmetric?[R]), ff: set[[D -> R]]):
      (FORALL x: least_bounded_above?({s | EXISTS f: ff(f) & s = f(x)}, alt))
       IMPLIES
       (FORALL (x1):
          least_bounded_above?[R]({s | EXISTS f: ff(f) & s = f(x1)}, alt));

  % Subtype TCC generated (at line 104, column 34) for  ff
      % expected type  S:
                     %   (LAMBDA (S: set[[D -> R]]):
                     %      greatest_bounded_below?(S, pointwise(alt)))
  glb_pointwise_def_TCC1: OBLIGATION
    FORALL (alt: (antisymmetric?[R]), ff: set[[D -> R]]):
      (FORALL x:
         greatest_bounded_below?({s | EXISTS f: ff(f) & s = f(x)}, alt))
       IMPLIES greatest_bounded_below?[[D -> R]](ff, pointwise(alt));

  % Subtype TCC generated (at line 105, column 28) for
      % {s | EXISTS f: ff(f) & s = f(x)}
      % expected type  S:
                     %   (LAMBDA (S: set[R]): greatest_bounded_below?(S, alt))
  glb_pointwise_def_TCC2: OBLIGATION
    FORALL (alt: (antisymmetric?[R]), ff: set[[D -> R]]):
      (FORALL x:
         greatest_bounded_below?({s | EXISTS f: ff(f) & s = f(x)}, alt))
       IMPLIES
       (FORALL (x1):
          greatest_bounded_below?[R]({s | EXISTS f: ff(f) & s = f(x1)}, alt));


body:
  % sets ordered by "subset?" form a complete lattice
  %
  % Author: Alfons Geser, National Institute of Aerospace
  % Date: Jan 2005

  sets_complete_lattices[T: TYPE]: THEORY

  BEGIN

    IMPORTING booleans_are_finite, pointwise_orders[T, bool]
    
    subset_equals_pointwise_implies: LEMMA
      subset?[T] = pointwise(IMPLIES)

    subset_is_a_complete_lattice: JUDGEMENT
      subset?[T] HAS_TYPE (complete_lattice?[set[T]])

    IMPORTING complete_lattices[set[T], subset?[T]]

  END sets_complete_lattices

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 16, column 4) for  subset?[T]
      % expected type  (complete_lattice?[set[T]])
  subset_is_a_complete_lattice: OBLIGATION
    complete_lattice?[set[T]](subset?[T]);


body:
  % Ordered sets (T, <=) that have a "complement" function, i.e.,
  % an involutorian, anti-monotone function from T to T.
  %

  complementary_orders[T: TYPE+]: THEORY

  BEGIN

    IMPORTING bounded_orders[T]

    rel: VAR pred[[T, T]]
    C: VAR [T -> T]
    t, t1, t2: VAR T
    S: VAR set[T]

    complement?(rel)(C): bool =
      C o C = id[T] & preserves(C, rel, converse(rel))

  %   complement_is_bijective: JUDGEMENT
  %     (complement?(rel)) SUBTYPE_OF (bijective?[T, T])

    complement_complement: LEMMA
      FORALL (C: (complement?(rel))): C(C(t)) = t

    image_complement: LEMMA
      FORALL (C: (complement?(rel))): image(C, image(C, S)) = S

    inverse_complement: LEMMA
      FORALL (C: (complement?(rel))): inverse[T, T](C) = C

  %   inverse_complement_is_complement: JUDGEMENT
  %     inverse[T, T](C: (complement?(rel))) HAS_TYPE (complement?(rel))

    le_complement: LEMMA
      FORALL (C: (complement?(rel))): rel(C(t1), C(t2)) IFF rel(t2, t1)

    upper_bound_complement: LEMMA
      FORALL (C: (complement?(rel))):
        upper_bound?[T](t, S, rel) IFF lower_bound?[T](C(t), image(C, S), rel)

    bounded_above_complement: LEMMA
      FORALL (C: (complement?(rel))):
        bounded_above?[T](S, rel) IFF bounded_below?[T](image(C, S), rel)

    least_upper_bound_complement: LEMMA
      FORALL (C: (complement?(rel))):
        least_upper_bound?[T](t, S, rel) IFF
        greatest_lower_bound?[T](C(t), image(C, S), rel)

    least_bounded_above_complement: LEMMA
      FORALL (C: (complement?(rel))):
        least_bounded_above?[T](S, rel) IFF
        greatest_bounded_below?[T](image(C, S), rel)

    lub_complement: LEMMA
      FORALL (rel: (antisymmetric?[T]), C: (complement?(rel)),
              S: (least_bounded_above?(rel))):
        lub[T](rel)(S) = C(glb[T](rel)(image(C, S)))

    glb_complement: LEMMA
      FORALL (rel: (antisymmetric?[T]), C: (complement?(rel)),
              S: (greatest_bounded_below?(rel))):
        glb[T](rel)(S) = C(lub[T](rel)(image(C, S)))

  END complementary_orders

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 58, column 37) for  image(C, S)
      % expected type  S:
                     %   (LAMBDA (S: set[T]): greatest_bounded_below?(S, rel))
  lub_complement_TCC1: OBLIGATION
    FORALL (rel: (antisymmetric?[T]), C: (complement?(rel)),
            S: (LAMBDA (S: set[T]): least_bounded_above?[T](S, rel))):
      greatest_bounded_below?[T](image[T, T](C, S), rel);

  % Subtype TCC generated (at line 63, column 37) for  image(C, S)
      % expected type  S: (LAMBDA (S: set[T]): least_bounded_above?(S, rel))
  glb_complement_TCC1: OBLIGATION
    FORALL (rel: (antisymmetric?[T]), C: (complement?(rel)),
            S: (LAMBDA (S: set[T]): greatest_bounded_below?[T](S, rel))):
      least_bounded_above?[T](image[T, T](C, S), rel);


body:
  % Lattices that have a "complement" function. See also complementary_orders.
  %

  complementary_lattices[
    T: TYPE+,
    (IMPORTING bounded_orders[T])
    <=: (lattice?[T])
  ]: THEORY

  BEGIN

    IMPORTING
      lattices[T, <=],
      minmax_orders[T],
      function_image_extra[T, T],
      complementary_orders[T]

    t, t1, t2: VAR T
    C, H: VAR [T -> T]
    S: VAR set[T]
    NF: VAR non_empty_finite_set[T]

  %   modular?(<=): bool =
  %     FORALL (a, c: T):
  %       a <= c => lub(<=)(a, glb(<=)(b, c)) = glb(<=)(lub(<=)(a, b), c)

    dual(C)(H): [T -> T] = C o H o C

    dual_dual : LEMMA
      FORALL (C: (complement?(<=))): dual(C)(dual(C)(H)) = H

    dual_inclusion1 : LEMMA
      FORALL (C: (complement?(<=))): H(C(t)) <= C(t) IFF t <= dual(C)(H)(t)

    dual_inclusion2 : LEMMA
      FORALL (C: (complement?(<=))): C(t) <= H(C(t)) IFF dual(C)(H)(t) <= t

    dual_inclusion3 : LEMMA
      FORALL (C: (complement?(<=))): H(t) <= t IFF C(t) <= dual(C)(H)(C(t))

    dual_inclusion4 : LEMMA
      FORALL (C: (complement?(<=))): t <= H(t) IFF dual(C)(H)(C(t)) <= C(t)


  END complementary_lattices


body:
  % if <= is a complete lower semilattice on T and f is a monotone function from
  % T to T, then f is a least fixed point of x iff f is the least prefixed point.
  %
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Nov 2004

  fixed_points[T: TYPE+]: THEORY

  BEGIN

    IMPORTING minmax_orders[T]

    R: VAR pred[[T, T]]
    <=: VAR (complete_lower_semilattice?[T])
    x, y: VAR T
    f: VAR [T -> T]

    monotone?(R)(f): bool = FORALL x, y: R(x, y) => R(f(x), f(y))
    fixed_point?(f)(x): bool = (f(x) = x)
    prefixed_point?(R)(f)(x): bool = R(f(x), x)
    lfp?(R)(f)(x): bool = least?(fixed_point?(f), R)(x)

    prefixed_points_closed: LEMMA
      FORALL (f: (monotone?(<=))):
        prefixed_point?(<=)(f)(x) => prefixed_point?(<=)(f)(f(x))

    prefixed_points_lower_bounds: LEMMA
      FORALL (f: (monotone?(<=))):
        lower_bound?[T](x, prefixed_point?(<=)(f), <=) =>
          lower_bound?[T](f(x), prefixed_point?(<=)(f), <=)

    least_prefixed_point_is_fixed_point: LEMMA
      FORALL (f: (monotone?(<=))):
        greatest_lower_bound?[T](x, prefixed_point?(<=)(f), <=) =>
          fixed_point?(f)(x)

    least_fixed_point_le_prefixed_points: LEMMA
      FORALL (f: (monotone?(<=))):
        lfp?(<=)(f)(x) => lower_bound?[T](x, prefixed_point?(<=)(f), <=)

    least_prefixed_point: THEOREM
      FORALL (f: (monotone?(<=))):
        lfp?(<=)(f)(x) IFF greatest_lower_bound?[T](x, prefixed_point?(<=)(f), <=)

    least_fixed_point_exists: COROLLARY
      FORALL (f: (monotone?(<=))):
        nonempty?(lfp?(<=)(f))

    least_fixed_point_unique: COROLLARY
      FORALL (f: (monotone?(<=))):
        unique?(lfp?(<=)(f))

  END fixed_points


body:
  % A simulation of Bruno Dutertre's fixedpoints/mucalculus_prop.
  %
  % Author: Alfons Geser, National Institute of Aerospace
  % Date: Feb 2005

  new_mucalculus_prop[T: TYPE]: THEORY

  BEGIN

    IMPORTING
      fixed_points[set[T]],
      sets_complete_lattices[T]

    leq_equals_subset: LEMMA <= = subset?[T]

    monotonic_is_monotone: JUDGEMENT
      (monotonic?[T]) SUBTYPE_OF (monotone?(subset?))

    leq_is_complete_lattice: JUDGEMENT
      <= HAS_TYPE (complete_lattice?[set[T]])

    IMPORTING complementary_lattices[set[T], <=]

    C: VAR (complement?(<=))
    F: VAR (monotonic?[T])
    p, q: VAR pred[T]
    x: VAR set[T]
    A: VAR set[pred[T]]

    fixpoint_equals_fixed_point: LEMMA
      fixpoint?(F) = fixed_point?[set[T]](F)

    fixpoint2_equals_fixed_point: LEMMA
      fixpoint?(F, x) = fixed_point?[set[T]](F)(x)

    antisymmetry: LEMMA p <= q AND q <= p IMPLIES p = q

    reflexivity: LEMMA p <= p


    %--- glb(A) is the greatest lower bound of A

    glb_equals_glb: LEMMA glb[T] = glb[set[T]](subset?)

    glb_lower_bound: LEMMA FORALL (q: (A)): glb(A) <= q

    glb_greatest_lower_bound: LEMMA
         p <= glb(A) IFF FORALL (q: (A)): p <= q


    %--- lub(A) is the least upper bound of A 

    lub_equals_lub: LEMMA lub[T] = lub[set[T]](subset?)

    lub_upper_bound: LEMMA FORALL (q: (A)): q <= lub(A)

    lub_least_upper_bound: LEMMA
         lub(A) <= p IFF FORALL (q: (A)): q <= p
    

    %--- properties of mu operator

    mu_equals_least_prefixed_point: LEMMA
      mu(F) = glb[set[T]](<=)(prefixed_point?(<=)(F))

    smallest_closed: PROPOSITION F(p) <= p IMPLIES mu(F) <= p

    fixpoint_mu2: PROPOSITION fixpoint?(F)(mu(F))

    fixpoint_mu1: PROPOSITION F(mu(F)) = mu(F)

    closure_mu: PROPOSITION F(mu(F)) <= mu(F)

    least_fixpoint2: PROPOSITION fixpoint?(F)(p) IMPLIES mu(F) <= p

    least_fixpoint1: PROPOSITION F(p) = p IMPLIES mu(F) <= p

    lfp_equals_lfp: LEMMA lfp?(F) = lfp?[set[T]](<=)(F)

    mu_lfp: JUDGEMENT mu(F) HAS_TYPE (lfp?(F))



    %--- fixed points and dual

    monotonic_dual_monotonic: JUDGEMENT dual(C)(F) HAS_TYPE (monotonic?[T])

    least_fixpoint_dual: PROPOSITION mu(dual(C)(F)) = C(nu(F))

    greatest_fixpoint_dual: PROPOSITION nu(dual(C)(F)) = C(mu(F))

    complement_is_complement: JUDGEMENT
      complement[T] HAS_TYPE (complement?(<=))


    %--- properties of nu operator

    closure_nu: PROPOSITION nu(F) <= F(nu(F))

    largest_closed: PROPOSITION p <= F(p) IMPLIES p <= nu(F)

    fixpoint_nu1: PROPOSITION F(nu(F)) = nu(F)

    fixpoint_nu2: PROPOSITION fixpoint?(F)(nu(F))

    greatest_fixpoint1: PROPOSITION F(p) = p IMPLIES p <= nu(F)

    greatest_fixpoint2: PROPOSITION fixpoint?(F)(p) IMPLIES p <= nu(F)

    nu_gfp: JUDGEMENT nu(F) HAS_TYPE (gfp?(F))

  END new_mucalculus_prop

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 17, column 4) for  x
      % expected type  (monotone?(subset?))
  monotonic_is_monotone: OBLIGATION
    FORALL (x: (monotonic?[T])): monotone?[set[T]](subset?[T])(x);

  % Judgement subtype TCC generated (at line 20, column 4) for  <=
      % expected type  (complete_lattice?[set[T]])
  leq_is_complete_lattice: OBLIGATION complete_lattice?[set[T]](<=[T]);

  % Subtype TCC generated (at line 64, column 28) for  prefixed_point?(<=)(F)
      % expected type  S:
                     %   (LAMBDA (S: set[set[T]]):
                     %      greatest_bounded_below?(S, <=))
  mu_equals_least_prefixed_point_TCC1: OBLIGATION
    FORALL (F: (monotonic?[T])):
      greatest_bounded_below?[set[T]]
          (prefixed_point?[set[T]](<=[T])(F), <=[T]);

  % Judgement subtype TCC generated (at line 80, column 20) for  mu(F)
      % expected type  (lfp?(F))
  mu_lfp: OBLIGATION FORALL (F): lfp?[T](F)(mu[T](F));

  % Judgement subtype TCC generated (at line 86, column 38) for  dual(C)(F)
      % expected type  (monotonic?[T])
  monotonic_dual_monotonic: OBLIGATION
    FORALL (C, F): monotonic?[T](dual[set[T], <=](C)(F));

  % Judgement subtype TCC generated (at line 93, column 4) for  complement[T]
      % expected type  (complement?(<=))
  complement_is_complement: OBLIGATION
    complement?[set[T]](<=[T])(complement[T]);

  % Judgement subtype TCC generated (at line 110, column 20) for  nu(F)
      % expected type  (gfp?(F))
  nu_gfp: OBLIGATION FORALL (F): gfp?[T](F)(nu[T](F));


body:
  % every infinite subset of int that is bounded below can be enumerated,
  % i.e., there is a strictly monotone surjective function from nat to it.
  %
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Dec 2004

  integer_enumerations[T: TYPE FROM int]: THEORY

  BEGIN

    IMPORTING
      infinite_sets_def[T],
      bounded_integers[T]
  %    bounded_sets[nat, <=]

    m, n, c: VAR nat
    f: VAR [nat -> T]

    enumerable?(S: set[T]): bool =
      bounded_below?[T](<=)(S) & is_infinite[T](S)

    enumerable_below_bounded: JUDGEMENT
      (enumerable?) SUBTYPE_OF (non_empty_bounded_below?[T])

    enumerable_infinite: JUDGEMENT
      (enumerable?) SUBTYPE_OF (is_infinite[T])

    remove_enumerable: JUDGEMENT
      remove(i: T, S: (enumerable?)) HAS_TYPE (enumerable?)

    S, S1, S2: VAR (enumerable?)

    strictly_monotone?(f): bool = FORALL m, n: m < n => f(m) < f(n)
  % same as:
  %     preserves(f,
  %       restrict[[real, real], [T, T], bool](<),
  %       restrict[[real, real], [T, T], bool](<))

    % the enumeration function for S, i.e., the function that enumerates
    % all elements of S in ascending order.
    enum(S)(n): RECURSIVE T =
      IF n = 0 THEN least[T](restrict[[real, real], [T, T], bool](<=))(S)
      ELSE enum(remove(least[T](restrict[[real, real], [T, T], bool](<=))(S), S))(n-1)
      ENDIF
    MEASURE n

    enum_member: JUDGEMENT
      enum(S)(n) HAS_TYPE (S)

  %   least_le: LEMMA
  %     FORALL (m: (S)):
  %       least(restrict[[real, real], [T, T], bool](<=))(S) <= m

    enum_surjective_lem: LEMMA
      FORALL (i: (S)):
        c = i - least(restrict[[real, real], [T, T], bool](<=))(S) =>
          EXISTS n: i = enum(S)(n)

    enum_surjective: LEMMA
      FORALL (i: (S)): EXISTS n: i = enum(S)(n)

    enum_def: THEOREM
      image(enum(S), fullset[nat]) = S

    enum_subset_monotone: LEMMA
      subset?(S1, S2) => enum(S2)(n) <= enum(S1)(n)

    enum_strictly_ascending: LEMMA
      enum(S)(n) < enum(S)(n + 1)

    enum_strictly_monotone: JUDGEMENT
      enum(S) HAS_TYPE (strictly_monotone?)

    enumerable: THEOREM
      EXISTS (f: (strictly_monotone?)): image(f, fullset[nat]) = S

    enum_bijective: LEMMA
      bijective?[nat, (S)](enum(S))

  END integer_enumerations

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 23, column 4) for  x
      % expected type  (non_empty_bounded_below?[T])
  enumerable_below_bounded: OBLIGATION
    FORALL (x: (enumerable?)): non_empty_bounded_below?[T](x);

  % Judgement subtype TCC generated (at line 26, column 4) for  x
      % expected type  (LAMBDA (S: set[T]): NOT is_finite(S))
  enumerable_infinite: OBLIGATION
    FORALL (x: (enumerable?)): NOT is_finite[T](x);

  % Judgement subtype TCC generated (at line 29, column 4) for  remove(i, S)
      % expected type  (enumerable?)
  remove_enumerable: OBLIGATION
    FORALL (S: (enumerable?), i: T): enumerable?(remove[T](i, S));

  % Subtype TCC generated (at line 43, column 80) for  n - 1
      % expected type  nat
  enum_TCC1: OBLIGATION
    FORALL (S: (enumerable?), n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Termination TCC generated (at line 43, column 9) for
      % enum(remove(least[T](restrict[[real, real], [T, T], bool](<=))(S), S))
      %     (n - 1)
  enum_TCC2: OBLIGATION
    FORALL (S: (enumerable?), n: nat): NOT n = 0 IMPLIES n - 1 < n;

  % Judgement subtype TCC generated (at line 48, column 4) for  enum(S)(n)
      % expected type  (S)
  enum_member: OBLIGATION FORALL (S, n): S(enum(S)(n));

  % Judgement subtype TCC generated (at line 72, column 4) for  enum(S)
      % expected type  (strictly_monotone?)
  enum_strictly_monotone: OBLIGATION FORALL (S): strictly_monotone?(enum(S));


body:
  % pointwise orders on functions whose domain is finite
  % their strict part preserves well-founded orders
  %
  % Author: Alfons Geser (geser@nianet.org), National Institute of Aerospace
  % Date: Dec 2004

  finite_pointwise_orders[D, R: TYPE]: THEORY

  BEGIN

  ASSUMING

    domain_finiteness: ASSUMPTION is_finite_type[D]

  ENDASSUMING

    IMPORTING
      numbers_infinite,         % to discharge a TCC of infinite_pigeonhole
      pointwise_orders[D, R],
      well_foundedness,
      infinite_pigeonhole[nat, D],
      integer_enumerations[nat]

    d: VAR D
    r: VAR R
    n: VAR nat
    rel: VAR (transitive?[R])
    seq: VAR [nat -> [D -> R]]
    g: VAR (preserves[nat, nat](<, <))  % enumerates the subsequence indices

    % an infinite sequence of elements from the finite type D must contain
    % a mono-chromatic subsequence
    infinite_pigeonhole: LEMMA
      FORALL (f: [nat -> D]): EXISTS d, g: FORALL n: f(g(n)) = d

    descending_exists: LEMMA
      descending?(strictly_pointwise(rel))(seq) =>
        EXISTS d: rel(seq(n + 1)(d), seq(n)(d))

    descending_reflexive_closure: LEMMA
      descending?(strictly_pointwise(rel))(seq) =>
        descending?[R](reflexive_closure[R](rel))(LAMBDA n: seq(n)(d))

    pointwise_pigeonhole: LEMMA
      descending?(strictly_pointwise(rel))(seq) =>
        EXISTS d, g: descending?(rel)(LAMBDA n: seq(g(n))(d))

    strictly_pointwise_well_founded_order: JUDGEMENT
      strictly_pointwise(rel: (well_founded_order?[R])) HAS_TYPE
        (well_founded_order?[[D -> R]])

  END finite_pointwise_orders

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 21, column 4) for
      % infinite_pigeonhole[nat, D]
      % generated from assumption infinite_pigeonhole.domain_infiniteness
  IMP_infinite_pigeonhole_TCC1: OBLIGATION NOT is_finite_type[nat];

  % Assuming TCC generated (at line 21, column 4) for
      % infinite_pigeonhole[nat, D]
      % generated from assumption infinite_pigeonhole.range_finiteness
  IMP_infinite_pigeonhole_TCC2: OBLIGATION is_finite_type[D];

  % Judgement subtype TCC generated (at line 49, column 4) for
      % strictly_pointwise(rel)
      % expected type  (well_founded_order?[[D -> R]])
  strictly_pointwise_well_founded_order: OBLIGATION
    FORALL (rel: (well_founded_order?[R])):
      well_founded_order?[[D -> R]](strictly_pointwise[D, R](rel));


body:
  top: THEORY
  BEGIN
      IMPORTING fundamental_theorem,
                table_of_integrals,
                taylors,
                % other  misc theories
                chain_rule,
                composition_continuous,
                continuous_lambda,
                sqrt_derivative,
                deriv_domains,
                derivatives_lam 
  END top


body:
  %----------------------------------------------------------------------------
  %  Continuous functions [ T -> real]   
  % 
  %  Defines:
  %      continuous?(f, x0)                  ---- continuity at a point
  %      continuous?(f, E)                   ---- continuity on a set
  %
  %  I some cases PVS has trouble disambiguating these, so the following are
  %  defined which helps.  See cont_if_fun for an example.
  %
  %      continuous_at?(f, x0)               ---- continuity at a point
  %      continuous_on?(f, E)                ---- continuity on a set
  %
  %
  %
  %----------------------------------------------------------------------------


  continuous_functions [ T : TYPE FROM real ] : THEORY
  BEGIN

    IMPORTING % lim_of_functions
              reals@real_fun_ops


    f, f1, f2      : VAR [T -> real]
    g              : VAR [T -> nzreal]
    u              : VAR real
    x, x0          : VAR T
    epsilon, delta : VAR posreal
    n              : VAR nat
   


    %--------------------
    %  Continuity at x0    
    %--------------------

    continuous?(f, x0) : bool = 
              FORALL epsilon : EXISTS delta : FORALL x :
                  abs(x - x0) < delta IMPLIES abs(f(x) - f(x0)) < epsilon


    continuous_at?(f, x0) : MACRO bool = continuous?(f, x0)

    %--- equivalent definitions ---%

    % continuity_def : LEMMA
    %       continuous?(f, x0) IFF convergence(f, x0, f(x0))

    % continuity_def2 : LEMMA
    %       continuous?(f, x0) IFF convergent?(f, x0)


    %---------------------------------------------
    %  Continuity of f in a subset of its domain
    %---------------------------------------------

    E: VAR setof[T]

    continuous_on?(f, E): bool = FORALL (x0: (E)): FORALL epsilon:
       EXISTS delta: FORALL (x:(E)): abs(x - x0) < delta IMPLIES abs(f(x) - f(x0)) < epsilon


    % continuous_on_def: LEMMA
    %     continuous_on?(f, E) IFF FORALL (y: (E)): convergence(f, E, y, f(y))



    %------------------------------------------
    %  Operations preserving continuity at x0 
    %------------------------------------------

    sum_continuous  : AXIOM continuous?(f1, x0) AND continuous?(f2, x0)
                             IMPLIES continuous?(f1 + f2, x0)

    diff_continuous : AXIOM continuous?(f1, x0) AND continuous?(f2, x0)
                             IMPLIES continuous?(f1 - f2, x0)

    prod_continuous : AXIOM continuous?(f1, x0) AND continuous?(f2, x0)
                             IMPLIES continuous?(f1 * f2, x0)

    const_continuous: AXIOM continuous?(const_fun(u), x0)

    scal_continuous : AXIOM continuous?(f, x0) IMPLIES continuous?(u * f, x0)
                  
    neg_continuous  : AXIOM continuous?(f, x0) IMPLIES continuous?(- f, x0)

    div_continuous  : AXIOM continuous?(f, x0) AND continuous?(g, x0) 
                              IMPLIES continuous?(f/g, x0)

    inv_continuous  : AXIOM continuous?(g, x0) IMPLIES continuous?(1/g, x0)
    
    identity_continuous: AXIOM continuous?(I[T], x0)

    expt_continuous : LEMMA continuous?(f, x0) IMPLIES continuous?(f^n, x0)


    %---------------------------------------------
    %  Continuity of f in a subset of its domain
    %---------------------------------------------

    F: VAR setof[real]


    %--- Operation preserving continuity in E ---%

    sum_set_continuous :  AXIOM continuous_on?(f1, E) AND continuous_on?(f2, E)
                                 IMPLIES continuous_on?(f1 + f2, E)

    diff_set_continuous : AXIOM continuous_on?(f1, E) AND continuous_on?(f2, E)
                                 IMPLIES continuous_on?(f1 - f2, E)
   
    prod_set_continuous : AXIOM continuous_on?(f1, E) AND continuous_on?(f2, E)
                                 IMPLIES continuous_on?(f1 * f2, E)

    const_set_continuous: LEMMA continuous_on?(const_fun(u), E)

    scal_set_continuous : AXIOM continuous_on?(f, E) IMPLIES continuous_on?(u * f, E)

    neg_set_continuous  : AXIOM continuous_on?(f, E) IMPLIES continuous_on?(- f, E)

    div_set_continuous  : AXIOM continuous_on?(f, E) AND continuous_on?(g, E) 
                                IMPLIES continuous_on?(f/g, E)

    inv_set_continuous  : AXIOM continuous_on?(g, E) IMPLIES continuous_on?(1/g, E)
    
    identity_set_continuous: LEMMA continuous_on?(I[T], E)

    
    %---------------------------------
    %  Continuity of f in its domain
    %---------------------------------

    continuous?(f): bool = FORALL x0: continuous?(f, x0)

    continuous_def2: LEMMA continuous?(f) IFF continuous_on?(f, T_pred)  

    continuity_subset2: LEMMA continuous?(f) IMPLIES continuous_on?(f, E)


    %--- Properties ---%

    continuous_fun: TYPE+ = { f | continuous?(f) }

    nz_continuous_fun: TYPE = { g | continuous?(g) }

    h, h1, h2: VAR continuous_fun
    h3: VAR nz_continuous_fun

    sum_fun_continuous : JUDGEMENT  +(h1, h2) HAS_TYPE continuous_fun

    diff_fun_continuous: JUDGEMENT  -(h1, h2) HAS_TYPE continuous_fun

    prod_fun_continuous: JUDGEMENT  *(h1, h2) HAS_TYPE continuous_fun

    const_fun_continuous: JUDGEMENT const_fun(u) HAS_TYPE continuous_fun

    scal_fun_continuous: JUDGEMENT  *(u, h) HAS_TYPE continuous_fun

    neg_fun_continuous  : JUDGEMENT -(h) HAS_TYPE continuous_fun

    div_fun_continuous : JUDGEMENT /(h, h3) HAS_TYPE continuous_fun

    id_fun_continuous  : JUDGEMENT I[T] HAS_TYPE continuous_fun



    inv_fun_continuous : LEMMA continuous?(1/h3)


    m,b: VAR real
    linear_fun_cont    : LEMMA continuous?(LAMBDA x: m*x + b) %% BUTLER

    one_over_x_cont    : LEMMA (FORALL x: x /= 0) IMPLIES
                                         continuous?((LAMBDA x: 1 / x))

    x_to_n_continuous  : LEMMA continuous?(LAMBDA x: x^n)   %% BUTLER

    expt_fun_continuous: LEMMA continuous?(f) IMPLIES continuous?(f^n)



  % ------------ Alternate forms and names for convenience ---------------

    sum_cont_fun  : LEMMA continuous?(f1) AND continuous?(f2)
                             IMPLIES continuous?(f1 + f2)

    diff_cont_fun : LEMMA continuous?(f1) AND continuous?(f2)
                             IMPLIES continuous?(f1 - f2)

    prod_cont_fun : LEMMA continuous?(f1) AND continuous?(f2)
                             IMPLIES continuous?(f1 * f2)

    const_cont_fun: LEMMA continuous?(const_fun(u))

    scal_cont_fun : LEMMA continuous?(f) IMPLIES continuous?(u * f)
                  
    neg_cont_fun    : LEMMA continuous?(f) IMPLIES continuous?(- f)

    div_cont_fun  : LEMMA continuous?(f) AND continuous?(g) 
                              IMPLIES continuous?(f/g)

    inv_cont_fun  : LEMMA continuous?(g) IMPLIES continuous?(1/g)
    
    identity_cont_fun: LEMMA continuous?(I[T])

  %  id_cont_fun      : LEMMA continuous?(LAMBDA (t: posreal): t)

    expt_cont_fun    : LEMMA continuous?(f) IMPLIES continuous?(f^n)


  END continuous_functions

addendum:
  %%% ================ Addendum: generated declarations ================

  % Existence TCC generated (at line 144, column 2) for
      % continuous_fun: TYPE+ = {f | continuous?(f)}
  continuous_fun_TCC1: OBLIGATION EXISTS (x: {f | continuous?(f)}): TRUE;

  % Judgement subtype TCC generated (at line 151, column 34) for  h1 + h2
      % expected type  continuous_fun
  sum_fun_continuous: OBLIGATION FORALL (h1, h2): continuous?((+[T])(h1, h2));

  % Judgement subtype TCC generated (at line 153, column 34) for  h1 - h2
      % expected type  continuous_fun
  diff_fun_continuous: OBLIGATION
    FORALL (h1, h2): continuous?((-[T])(h1, h2));

  % Judgement subtype TCC generated (at line 155, column 34) for  h1 * h2
      % expected type  continuous_fun
  prod_fun_continuous: OBLIGATION FORALL (h1, h2): continuous?(*[T](h1, h2));

  % Judgement subtype TCC generated (at line 157, column 34) for  const_fun(u)
      % expected type  continuous_fun
  const_fun_continuous: OBLIGATION FORALL (u): continuous?(const_fun[T](u));

  % Judgement subtype TCC generated (at line 159, column 34) for  u * h
      % expected type  continuous_fun
  scal_fun_continuous: OBLIGATION FORALL (h, u): continuous?(*[T](u, h));

  % Judgement subtype TCC generated (at line 161, column 34) for  -h
      % expected type  continuous_fun
  neg_fun_continuous: OBLIGATION FORALL (h): continuous?(-h);

  % Judgement subtype TCC generated (at line 163, column 33) for  h / h3
      % expected type  continuous_fun
  div_fun_continuous: OBLIGATION FORALL (h, h3): continuous?(/[T](h, h3));

  % Judgement subtype TCC generated (at line 165, column 33) for  I[T]
      % expected type  continuous_fun
  id_fun_continuous: OBLIGATION continuous?(I[T]);

  % Subtype TCC generated (at line 176, column 66) for  x
      % expected type  nznum
  one_over_x_cont_TCC1: OBLIGATION
    (FORALL x: x /= 0) IMPLIES (FORALL (x1): x1 /= 0);

  % Subtype TCC generated (at line 178, column 53) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  x_to_n_continuous_TCC1: OBLIGATION FORALL (n: nat, x): x /= 0 OR n >= 0;


body:
  deriv_domain_def[T : TYPE FROM real]: THEORY
  BEGIN

     deriv_domain?: bool = FORALL (e: posreal, x:T):
                                    EXISTS (y: {u: nzreal | T_pred(u + x)}): abs(y) < e

     not_one_element?: bool = (FORALL (x: T): EXISTS (y: T): x /= y)

     connected?: bool =   FORALL (x, y : T), (z : real): x <= z AND z <= y IMPLIES T_pred(z)


     connected_deriv_domain: LEMMA connected? AND not_one_element?
                              IMPLIES deriv_domain?

     del_neigh_all?: bool = FORALL (a: T): EXISTS (del: posreal): FORALL (xx:real):
                              abs(xx-a) < del IMPLIES T_pred(xx)


  %  The following lemma shows that our derivative domain is more general than just
  %  having a delta neighborhood around every point.

     del_neigh_all_lem : LEMMA del_neigh_all? IMPLIES deriv_domain?


  END deriv_domain_def


body:
  derivatives_def  [ T : TYPE FROM real ] : THEORY
  %-----------------------------------------------------------------------------------------
  %
  %    The derivatives library has been generalized to handle a larger class of domains.
  %    Previously the domain had to be a connected domain defined by the following
  %    predicate:
  %
  %       connected_domain : ASSUMPTION
  %           FORALL (x, y : T), (z : real) :
  %               x <= z AND z <= y IMPLIES T_pred(z)
  %
  %    The following more general domain definition is now used
  %
  %        deriv_domain    : ASSUMPTION FORALL (e: posreal, x:T):
  %                                        EXISTS (y: {u: nzreal | T_pred(u + x)}): abs(y) < e
  %
  %    This definition allows unions of closed and open intervals.
  %    See deriv_domains for more information.
  %
  %-----------------------------------------------------------------------------------------
  BEGIN

    ASSUMING
      IMPORTING deriv_domain_def

      deriv_domain     : ASSUMPTION deriv_domain?[T]

      not_one_element  : ASSUMPTION not_one_element?[T]

    ENDASSUMING

    IMPORTING % lim_of_functions, 
              continuous_functions

    f, f1, f2, fp : VAR [T -> real]
    g : VAR [T -> nzreal]
    x : VAR T
    u : VAR nzreal
    b : VAR real
    l, l1, l2 : VAR real


  %   %-------------------
  %   %  Newton Quotient 
  %   %-------------------

  %   A(x) : setof[nzreal] = { u: nzreal | T_pred(x + u) }

  %   NQ(f, x)(h : (A(x))) : real = (f(x + h) - f(x)) / h

  %   deriv_TCC : LEMMA FORALL x : adh[(A(x))](fullset[real])(0)
  %   adh_A_lem : LEMMA adh[(A(x))](fullset[real])(0)   %% Butler

  % %   play: LEMMA (FORALL (x:T): EXISTS (e: posreal):  
  % %      FORALL (y: real): abs(x-y) < e IMPLIES T_pred(y))
  % %               IMPLIES
  % %                  adh[(A(x))](fullset[real])(0)

  %   %----------------------------
  %   %  Differentiable functions
  %   %----------------------------

    derivable?(f, x) : bool % = convergent?(NQ(f, x), 0)

  %% +++  derivable?(f) : bool = FORALL x : derivable?(f, x)


    %--------------------------------------
    %  Derivable functions are continuous
    %--------------------------------------

    % continuous_lim  : LEMMA convergence(LAMBDA (h : (A(x))) : f(x + h), 0, f(x))
    %                           IFF continuous?(f, x)

    % deriv_continuous      : LEMMA convergence(NQ(f, x), 0, l) 
    %                                 IMPLIES continuous?(f, x)   

    derivable_continuous  : AXIOM derivable?(f, x) IMPLIES continuous?(f, x)


  %% +++  derivable_cont_fun : LEMMA derivable?(f) IMPLIES continuous?(f)


    %---------------------
    %  Properties of NQ
    %---------------------

    % sum_NQ      : LEMMA NQ(f1 + f2, x) = NQ(f1, x) + NQ(f2, x)

    % neg_NQ      : LEMMA NQ(- f, x) = - NQ(f, x)

    % diff_NQ     : LEMMA NQ(f1 - f2, x) = NQ(f1, x) - NQ(f2, x)

    % scal_NQ     : LEMMA NQ(b * f, x) = b * NQ(f, x)

    % const_NQ    : LEMMA NQ(const_fun(b), x) = const_fun(0)

    % identity_NQ : LEMMA NQ(I[T], x) = const_fun(1)


    % prod_NQ     : LEMMA FORALL (h : (A(x))): NQ(f1 * f2, x)(h) 
    %                           = NQ(f1, x)(h) * f2(x) + NQ(f2, x)(h) * f1(x + h)

    % cnv_seq_prod_NQ: LEMMA convergence(NQ(f1, x), 0, l1)
    %                         AND convergence(NQ(f2, x), 0, l2)
    %             IMPLIES convergence(NQ(f1 * f2, x), 0, f2(x) * l1 + f1(x) * l2)


    % inv_NQ         : LEMMA FORALL (h : (A(x))) : NQ(1/g, x)(h) 
    %                                  = - NQ(g, x)(h) / (g(x) * g(x + h))
    
    % cnv_seq_inv_NQ : LEMMA convergence(NQ(g, x), 0, l1)
    %                      IMPLIES convergence(NQ(1/g, x), 0, - l1 / (g(x) * g(x)))


    %---------------------------------------
    %  Operations preserving derivability
    %---------------------------------------
   
    sum_derivable     : AXIOM derivable?(f1, x) AND derivable?(f2, x)
                                 IMPLIES derivable?(f1 + f2, x)

    neg_derivable     : AXIOM derivable?(f, x) IMPLIES derivable?(- f, x)

    diff_derivable    : AXIOM derivable?(f1, x) AND derivable?(f2, x)
                                 IMPLIES derivable?(f1 - f2, x)

    prod_derivable    : AXIOM derivable?(f1, x) AND derivable?(f2, x)
                                 IMPLIES derivable?(f1 * f2, x)

    scal_derivable    : AXIOM derivable?(f, x) IMPLIES derivable?(b * f, x)

    const_derivable   : AXIOM derivable?(const_fun(b), x)

    inv_derivable     : AXIOM derivable?(g, x) IMPLIES derivable?(1/g, x)

    div_derivable     : LEMMA derivable?(f, x) AND derivable?(g, x)
                                 IMPLIES derivable?(f / g, x)

    identity_derivable: AXIOM derivable?(I, x)


    %--------------
    %  Derivative
    %--------------

    deriv(f, (x0 : { x | derivable?(f, x) })) : real % = lim(NQ(f, x0), 0)

    % deriv_def   : LEMMA convergence(NQ(f, x), 0, l) IMPLIES
    %                  derivable?(f,x) AND deriv(f,x) = l

    deriv_sum   : AXIOM derivable?(f1, x) AND derivable?(f2, x) IMPLIES
                        deriv(f1 + f2, x) = deriv(f1, x) + deriv(f2, x)

    deriv_neg   : AXIOM derivable?(f, x) IMPLIES 
                        deriv(- f, x) = - deriv(f, x)

    deriv_diff  : AXIOM derivable?(f1, x) AND derivable?(f2, x) IMPLIES
                           deriv(f1 - f2, x) = deriv(f1, x) - deriv(f2, x)

    deriv_prod  : AXIOM derivable?(f1, x) AND derivable?(f2, x) IMPLIES
                           deriv(f1 * f2, x) = deriv(f1, x) * f2(x) 
                                               + deriv(f2, x) * f1(x)

    deriv_const : AXIOM deriv(const_fun(b), x) = 0

    deriv_scal  : AXIOM derivable?(f, x) IMPLIES deriv(b * f, x) = b * deriv(f, x)

    deriv_inv   : AXIOM derivable?(g, x) IMPLIES
                           deriv(1/g, x) = - deriv(g, x) / (g(x) * g(x))

    deriv_div   : LEMMA derivable?(f, x) AND derivable?(g, x) IMPLIES 
                           deriv(f / g, x) = 
                                 (deriv(f,x)*g(x) - deriv(g,x)*f(x))/(g(x)*g(x))

    deriv_identity : AXIOM deriv(I[T], x) = 1


  END derivatives_def

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 153, column 37) for  x
      % expected type  {x | derivable?(f1 + f2, x)}
  deriv_sum_TCC1: OBLIGATION
    FORALL (f1, f2: [T -> real], x: T):
      derivable?(f2, x) AND derivable?(f1, x) IMPLIES
       derivable?((+[T])(f1, f2), x);

  % Subtype TCC generated (at line 156, column 33) for  x
      % expected type  {x | derivable?(-f, x)}
  deriv_neg_TCC1: OBLIGATION
    FORALL (f: [T -> real], x: T): derivable?(f, x) IMPLIES derivable?(-f, x);

  % Subtype TCC generated (at line 159, column 40) for  x
      % expected type  {x | derivable?(f1 - f2, x)}
  deriv_diff_TCC1: OBLIGATION
    FORALL (f1, f2: [T -> real], x: T):
      derivable?(f2, x) AND derivable?(f1, x) IMPLIES
       derivable?((-[T])(f1, f2), x);

  % Subtype TCC generated (at line 162, column 40) for  x
      % expected type  {x | derivable?(f1 * f2, x)}
  deriv_prod_TCC1: OBLIGATION
    FORALL (f1, f2: [T -> real], x: T):
      derivable?(f2, x) AND derivable?(f1, x) IMPLIES
       derivable?(*[T](f1, f2), x);

  % Subtype TCC generated (at line 165, column 42) for  x
      % expected type  {x | derivable?(const_fun(b), x)}
  deriv_const_TCC1: OBLIGATION
    FORALL (b: real, x: T): derivable?(const_fun[T](b), x);

  % Subtype TCC generated (at line 167, column 60) for  x
      % expected type  {x | derivable?(b * f, x)}
  deriv_scal_TCC1: OBLIGATION
    FORALL (b: real, f: [T -> real], x: T):
      derivable?(f, x) IMPLIES derivable?(*[T](b, f), x);

  % Subtype TCC generated (at line 170, column 36) for  x
      % expected type  {x | derivable?(1 / g, x)}
  deriv_inv_TCC1: OBLIGATION
    FORALL (g: [T -> nzreal], x: T):
      derivable?(g, x) IMPLIES derivable?(/[T](1, g), x);

  % Subtype TCC generated (at line 173, column 38) for  x
      % expected type  {x | derivable?(f / g, x)}
  deriv_div_TCC1: OBLIGATION
    FORALL (f: [T -> real], g: [T -> nzreal], x: T):
      derivable?(g, x) AND derivable?(f, x) IMPLIES derivable?(/[T](f, g), x);

  % Subtype TCC generated (at line 176, column 37) for  x
      % expected type  {x | derivable?(I[T], x)}
  deriv_identity_TCC1: OBLIGATION FORALL (x: T): derivable?(I[T], x);


body:
  derivatives [T: TYPE FROM real ] : THEORY
  %-----------------------------------------------------------------------------------------
  %
  %    The derivatives library has been generalized to handle a larger class of domains.
  %    The following more general domain definition is now used
  %
  %        deriv_domain    : ASSUMPTION FORALL (e: posreal, x:T):
  %                                        EXISTS (y: {u: nzreal | T_pred(u + x)}): abs(y) < e
  %
  %    This definition allows unions of closed and open intervals.
  %    See deriv_domain and deriv_domains for more information and useful lemmas.
  %    
  %    See "derivatives_lam" for lambda-expression versions of the lemmas that are especially
  %    suited to rewriting.  Note that when you expand a function, the PVS system does not
  %    expand the definition using the real_fun_ops.  Instead it exapnds them using
  %    lambda expressions.
  %
  %-----------------------------------------------------------------------------------------
  BEGIN

    ASSUMING
      IMPORTING deriv_domain_def

      deriv_domain     : ASSUMPTION deriv_domain?[T]

      not_one_element  : ASSUMPTION not_one_element?[T]

    ENDASSUMING

    IMPORTING derivatives_def[T]

    f, f1, f2, fp : VAR [T -> real]
    g : VAR [T -> nzreal]
    x : VAR T
    u : VAR nzreal
    b : VAR real
    l, l1, l2 : VAR real


    derivable?(f) : bool = FORALL x : derivable?(f, x)
    
    differentiable?(f): MACRO bool = derivable?(f)

    deriv_fun    : TYPE = { f:[T -> real] | derivable?(f) }

    nz_deriv_fun : TYPE = { g:[T -> nzreal] | derivable?(g) }

    deriv(ff: deriv_fun)    : [T -> real] = LAMBDA x : deriv(ff, x)


    derivable_cont_fun     : LEMMA derivable?(f) IMPLIES continuous?(f)


    sum_derivable_fun      : LEMMA derivable?(f1) AND derivable?(f2)
                                 IMPLIES derivable?(f1 + f2)

    neg_derivable_fun      : LEMMA derivable?(f) IMPLIES derivable?(- f)

    diff_derivable_fun     : LEMMA derivable?(f1) AND derivable?(f2)
                                 IMPLIES derivable?(f1 - f2)

    prod_derivable_fun     : LEMMA derivable?(f1) AND derivable?(f2)
                                 IMPLIES derivable?(f1 * f2)

    scal_derivable_fun     : LEMMA derivable?(f) IMPLIES derivable?(b * f)

    const_derivable_fun    : LEMMA derivable?(LAMBDA x: b)

    inv_derivable_fun      : LEMMA derivable?(g) IMPLIES derivable?(1/g)

    div_derivable_fun      : LEMMA derivable?(f) AND derivable?(g)
                               IMPLIES derivable?(f / g)

    identity_derivable_fun : LEMMA derivable?(I)

    id_derivable_fun       : LEMMA derivable?(LAMBDA x: x)
          

    ff, ff1, ff2 : VAR deriv_fun
    gg : VAR nz_deriv_fun

    derivable_cont   : JUDGEMENT deriv_fun SUBTYPE_OF continuous_fun[T]

    nz_derivable_cont: JUDGEMENT nz_deriv_fun SUBTYPE_OF nz_continuous_fun[T]

    derivable_sum    : JUDGEMENT +(ff1, ff2) HAS_TYPE deriv_fun

    derivable_diff   : JUDGEMENT -(ff1, ff2) HAS_TYPE deriv_fun

    derivable_prod   : JUDGEMENT *(ff1, ff2) HAS_TYPE deriv_fun

    derivable_scal   : JUDGEMENT *(b, ff) HAS_TYPE deriv_fun

    derivable_neg    : JUDGEMENT -(ff) HAS_TYPE deriv_fun

    derivable_div    : JUDGEMENT /(ff, gg) HAS_TYPE deriv_fun

    derivable_inv    : JUDGEMENT /(b, gg) HAS_TYPE deriv_fun

    derivable_const  : JUDGEMENT const_fun(b) HAS_TYPE deriv_fun

    derivable_id     : JUDGEMENT I[T] HAS_TYPE deriv_fun


    %------------------------
    %  Derivative function
    %------------------------

    % deriv_fun_def: LEMMA (FORALL x: convergence(NQ(f, x), 0, fp(x))) IMPLIES
    %                       derivable?(f) AND deriv(f) = fp

    deriv_sum_fun  : LEMMA deriv(ff1 + ff2) = deriv(ff1) + deriv(ff2)

    deriv_neg_fun  : LEMMA deriv(- ff) = - deriv(ff)

    deriv_diff_fun : LEMMA deriv(ff1 - ff2) = deriv(ff1) - deriv(ff2)

    deriv_prod_fun : LEMMA deriv(ff1 * ff2) = deriv(ff1) * ff2 + deriv(ff2) * ff1

    deriv_scal_fun : LEMMA deriv(b * ff) = b * deriv(ff)

    deriv_inv_fun  : LEMMA deriv(1 / gg) = - deriv(gg) / (gg * gg)

    deriv_scaldiv_fun : LEMMA deriv(b / gg) = - (b * deriv(gg)) / (gg * gg)

    deriv_div_fun  : LEMMA deriv(ff / gg) = (deriv(ff)*gg - deriv(gg)*ff)/(gg*gg)

    deriv_const_fun: LEMMA deriv(LAMBDA x: b) = (LAMBDA x: 0)

    deriv_const_func: LEMMA deriv(const_fun(b)) = const_fun(0)

    deriv_id_fun    : LEMMA deriv(LAMBDA x: x) = (LAMBDA x: 1)

    deriv_I_fun     : LEMMA deriv(I) = (LAMBDA x: 1)

  % ------------------ following added by Rick Butler ---------------------

    n: VAR nat
  %  ^(f,n): [T -> real] =  (LAMBDA (t:T): f(t)^n)

    deriv_linear_fun: LEMMA FORALL (m,b: real):
                              LET f = (LAMBDA x: m*x + b) IN
                                 derivable?(f) AND deriv(f) = (LAMBDA x: m)

    deriv_exp_fun: AXIOM derivable?(f) AND n > 0 IMPLIES
                         derivable?(f^n) AND
                         deriv(f^n) = n*f^(n-1)*deriv(f)

    
    deriv_x_n    : LEMMA n > 0 AND f = (LAMBDA x: x^n) IMPLIES
                            derivable?(f) AND deriv(f) = (LAMBDA x: n*x^(n-1))

    deriv_x_to_n : LEMMA FORALL (n: posnat, a: real):
                           LET f = (LAMBDA x: a*x^n) IN
                              derivable?(f) AND deriv(f) = (LAMBDA x: a*n*x^(n-1))

  END derivatives

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 30, column 12) for  derivatives_def[T]
      % generated from assumption derivatives_def.deriv_domain
  IMP_derivatives_def_TCC1: OBLIGATION deriv_domain?[T];

  % Assuming TCC generated (at line 30, column 12) for  derivatives_def[T]
      % generated from assumption derivatives_def.not_one_element
  IMP_derivatives_def_TCC2: OBLIGATION not_one_element?[T];

  % Subtype TCC generated (at line 48, column 63) for  x
      % expected type  {x | derivable?(ff, x)}
  deriv_TCC1: OBLIGATION FORALL (ff: deriv_fun, x): derivable?[T](ff, x);

  % Judgement subtype TCC generated (at line 82, column 31) for  x
      % expected type  continuous_fun[T]
  derivable_cont: OBLIGATION FORALL (x: deriv_fun): continuous?[T](x);

  % Judgement subtype TCC generated (at line 84, column 31) for  x
      % expected type  nz_continuous_fun[T]
  nz_derivable_cont: OBLIGATION FORALL (x: nz_deriv_fun): continuous?[T](x);

  % Judgement subtype TCC generated (at line 86, column 31) for  ff1 + ff2
      % expected type  deriv_fun
  derivable_sum: OBLIGATION FORALL (ff1, ff2): derivable?((+[T])(ff1, ff2));

  % Judgement subtype TCC generated (at line 88, column 31) for  ff1 - ff2
      % expected type  deriv_fun
  derivable_diff: OBLIGATION FORALL (ff1, ff2): derivable?((-[T])(ff1, ff2));

  % Judgement subtype TCC generated (at line 90, column 31) for  ff1 * ff2
      % expected type  deriv_fun
  derivable_prod: OBLIGATION FORALL (ff1, ff2): derivable?(*[T](ff1, ff2));

  % Judgement subtype TCC generated (at line 92, column 31) for  b * ff
      % expected type  deriv_fun
  derivable_scal: OBLIGATION FORALL (b, ff): derivable?(*[T](b, ff));

  % Judgement subtype TCC generated (at line 94, column 31) for  -ff
      % expected type  deriv_fun
  derivable_neg: OBLIGATION FORALL (ff): derivable?(-ff);

  % Judgement subtype TCC generated (at line 96, column 31) for  ff / gg
      % expected type  deriv_fun
  derivable_div: OBLIGATION FORALL (ff, gg): derivable?(/[T](ff, gg));

  % Judgement subtype TCC generated (at line 98, column 31) for  b / gg
      % expected type  deriv_fun
  derivable_inv: OBLIGATION FORALL (b, gg): derivable?(/[T](b, gg));

  % Judgement subtype TCC generated (at line 100, column 31) for  const_fun(b)
      % expected type  deriv_fun
  derivable_const: OBLIGATION FORALL (b): derivable?(const_fun[T](b));

  % Judgement subtype TCC generated (at line 102, column 31) for  I[T]
      % expected type  deriv_fun
  derivable_id: OBLIGATION derivable?(I[T]);

  % Subtype TCC generated (at line 122, column 56) for  (gg * gg)
      % expected type  [T -> nzreal]
  deriv_inv_fun_TCC1: OBLIGATION
    FORALL (gg: nz_deriv_fun, x1: T): (*[T](gg, gg))(x1) /= 0;

  % Subtype TCC generated (at line 128, column 31) for  LAMBDA x: b
      % expected type  deriv_fun
  deriv_const_fun_TCC1: OBLIGATION FORALL (b: real): derivable?(LAMBDA x: b);

  % Subtype TCC generated (at line 132, column 32) for  LAMBDA x: x
      % expected type  deriv_fun
  deriv_id_fun_TCC1: OBLIGATION derivable?(LAMBDA x: x);

  % Subtype TCC generated (at line 147, column 41) for  (n - 1)
      % expected type  nat
  deriv_exp_fun_TCC1: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      n > 0 AND derivable?(f) AND derivable?(f ^ n) IMPLIES (n - 1) >= 0;

  % Subtype TCC generated (at line 150, column 50) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  deriv_x_n_TCC1: OBLIGATION
    FORALL (n: nat): n > 0 IMPLIES (FORALL (x): x /= 0 OR n >= 0);

  % Subtype TCC generated (at line 151, column 71) for  (n - 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  deriv_x_n_TCC2: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      (f = (LAMBDA x: x ^ n)) AND n > 0 AND derivable?(f) IMPLIES
       (FORALL (x1): x1 /= 0 OR (n - 1) >= 0);

  % Subtype TCC generated (at line 154, column 48) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  deriv_x_to_n_TCC1: OBLIGATION FORALL (n: posnat, x): x /= 0 OR n >= 0;

  % Subtype TCC generated (at line 155, column 75) for  (n - 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  deriv_x_to_n_TCC2: OBLIGATION
    FORALL (n: posnat, a: real, f: [T -> real]):
      derivable?(f) AND f = (LAMBDA x: a * x ^ n) IMPLIES
       (FORALL (x1): x1 /= 0 OR (n - 1) >= 0);


body:
  derivatives_lam[T: TYPE FROM real ]: THEORY
  %------------------------------------------------------------------------------ 
  % This theory has been created to support auto-rewriting, e.g.
  %
  %    auto-rewrite-theory "derivatives_lam[T]"
  %
  % or via special strategies
  %------------------------------------------------------------------------------ 
  BEGIN

    ASSUMING

      IMPORTING deriv_domain_def

      deriv_domain     : ASSUMPTION deriv_domain?[T]

      not_one_element  : ASSUMPTION not_one_element?[T]

    ENDASSUMING

    IMPORTING derivatives[T],
              reals@sq


    t   : VAR T
    a   : VAR real
    b   : VAR nzreal
    n   : VAR nat
    m   : VAR posnat
    f,g : VAR deriv_fun
    k   : VAR nz_deriv_fun

    derivable_id_lam     : LEMMA derivable?(LAMBDA(t):t)
    derivable_const_lam  : LEMMA derivable?(LAMBDA(t):a)
    derivable_add_lam    : LEMMA derivable?(LAMBDA(t):f(t)+g(t))
    derivable_mult_lam   : LEMMA derivable?(LAMBDA(t):f(t)*g(t))
    derivable_pow_lam    : LEMMA derivable?(LAMBDA(t):t^n)
    derivable_scal1_lam  : LEMMA derivable?(LAMBDA(t): a*f(t))
    derivable_scal2_lam  : LEMMA derivable?(LAMBDA(t): f(t)*a)
    derivable_neg_lam    : LEMMA derivable?(LAMBDA(t):-g(t))
    derivable_sub_lam    : LEMMA derivable?(LAMBDA(t):f(t)-g(t))
    derivable_sq_lam     : LEMMA derivable?(LAMBDA(t):sq(t))
    derivable_div_lam    : LEMMA derivable?(LAMBDA(t):f(t)/k(t))
    derivable_scald1_lam : LEMMA derivable?(LAMBDA(t): a/k(t))
    derivable_scald2_lam : LEMMA derivable?(LAMBDA(t): f(t)/b)

    deriv_id_lam         : LEMMA deriv(LAMBDA(t):t) = LAMBDA(t):1
        
    deriv_const_lam      : LEMMA deriv(LAMBDA(t):a) = LAMBDA(t):0
         
    deriv_add_lam        : LEMMA deriv(LAMBDA(t):f(t)+g(t)) = LAMBDA(t): deriv(f)(t) + deriv(g)(t)
        
    deriv_mult_lam       : LEMMA deriv(LAMBDA(t):f(t)*g(t)) 
                                   = LAMBDA(t):deriv(f)(t)*g(t) + deriv(g)(t)*f(t)

    deriv_pow_lam        : LEMMA deriv(LAMBDA(t):t^m) = LAMBDA(t):(m*t^(m-1))

    deriv_scal1_lam      : LEMMA deriv(LAMBDA(t): a*f(t)) = LAMBDA(t):a*deriv(f)(t)

    deriv_scal2_lam      : LEMMA deriv(LAMBDA(t): f(t)*a) = LAMBDA(t):a*deriv(f)(t)

    deriv_neg_lam        : LEMMA deriv(LAMBDA(t):-g(t)) = LAMBDA(t):-deriv(g)(t)

    deriv_sub_lam        : LEMMA deriv(LAMBDA(t):f(t)-g(t)) = LAMBDA(t):deriv(f)(t)-deriv(g)(t)

    deriv_sq_lam         : LEMMA deriv(LAMBDA(t):sq(t)) = LAMBDA(t):2*t

    deriv_div_lam        : LEMMA deriv(LAMBDA(t):f(t)/k(t)) 
                                    = LAMBDA(t):(deriv(f)(t)*k(t) - deriv(k)(t)*f(t)) / sq(k(t))

    deriv_scald1_lam     : LEMMA deriv(LAMBDA(t): a/k(t)) 
                                    = LAMBDA(t):-a*deriv(k)(t)/sq(k(t))

    deriv_scald2_lam     : LEMMA deriv(LAMBDA(t): f(t)/b) = LAMBDA(t):(deriv(f)(t))/b

  END derivatives_lam

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 21, column 12) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  IMP_derivatives_TCC1: OBLIGATION deriv_domain?[T];

  % Assuming TCC generated (at line 21, column 12) for  derivatives[T]
      % generated from assumption derivatives.not_one_element
  IMP_derivatives_TCC2: OBLIGATION not_one_element?[T];

  % Subtype TCC generated (at line 37, column 54) for  n
      % expected type  {i: int | t /= 0 OR i >= 0}
  derivable_pow_lam_TCC1: OBLIGATION FORALL (n: nat, t: T): t /= 0 OR n >= 0;

  % Subtype TCC generated (at line 47, column 37) for  LAMBDA (t): t
      % expected type  deriv_fun[T]
  deriv_id_lam_TCC1: OBLIGATION derivable?[T](LAMBDA (t): t);

  % Subtype TCC generated (at line 49, column 37) for  LAMBDA (t): a
      % expected type  deriv_fun[T]
  deriv_const_lam_TCC1: OBLIGATION
    FORALL (a: real): derivable?[T](LAMBDA (t): a);

  % Subtype TCC generated (at line 51, column 37) for  LAMBDA (t): f(t) + g(t)
      % expected type  deriv_fun[T]
  deriv_add_lam_TCC1: OBLIGATION
    FORALL (f, g: deriv_fun[T]): derivable?[T](LAMBDA (t): f(t) + g(t));

  % Subtype TCC generated (at line 53, column 37) for  LAMBDA (t): f(t) * g(t)
      % expected type  deriv_fun[T]
  deriv_mult_lam_TCC1: OBLIGATION
    FORALL (f, g: deriv_fun[T]): derivable?[T](LAMBDA (t): f(t) * g(t));

  % Subtype TCC generated (at line 56, column 49) for  m
      % expected type  {i: int | t /= 0 OR i >= 0}
  deriv_pow_lam_TCC1: OBLIGATION FORALL (m: posnat, t: T): t /= 0 OR m >= 0;

  % Subtype TCC generated (at line 56, column 37) for  LAMBDA (t): t ^ m
      % expected type  deriv_fun[T]
  deriv_pow_lam_TCC2: OBLIGATION
    FORALL (m: posnat): derivable?[T](LAMBDA (t): t ^ m);

  % Subtype TCC generated (at line 56, column 70) for  (m - 1)
      % expected type  {i: int | t /= 0 OR i >= 0}
  deriv_pow_lam_TCC3: OBLIGATION
    FORALL (m: posnat, t: T): t /= 0 OR (m - 1) >= 0;

  % Subtype TCC generated (at line 58, column 37) for  LAMBDA (t): a * f(t)
      % expected type  deriv_fun[T]
  deriv_scal1_lam_TCC1: OBLIGATION
    FORALL (a: real, f: deriv_fun[T]): derivable?[T](LAMBDA (t): a * f(t));

  % Subtype TCC generated (at line 60, column 37) for  LAMBDA (t): f(t) * a
      % expected type  deriv_fun[T]
  deriv_scal2_lam_TCC1: OBLIGATION
    FORALL (a: real, f: deriv_fun[T]): derivable?[T](LAMBDA (t): f(t) * a);

  % Subtype TCC generated (at line 62, column 37) for  LAMBDA (t): -g(t)
      % expected type  deriv_fun[T]
  deriv_neg_lam_TCC1: OBLIGATION
    FORALL (g: deriv_fun[T]): derivable?[T](LAMBDA (t): -g(t));

  % Subtype TCC generated (at line 64, column 37) for  LAMBDA (t): f(t) - g(t)
      % expected type  deriv_fun[T]
  deriv_sub_lam_TCC1: OBLIGATION
    FORALL (f, g: deriv_fun[T]): derivable?[T](LAMBDA (t): f(t) - g(t));

  % Subtype TCC generated (at line 66, column 37) for  LAMBDA (t): sq(t)
      % expected type  deriv_fun[T]
  deriv_sq_lam_TCC1: OBLIGATION derivable?[T](LAMBDA (t): sq(t));

  % Subtype TCC generated (at line 68, column 37) for  LAMBDA (t): f(t) / k(t)
      % expected type  deriv_fun[T]
  deriv_div_lam_TCC1: OBLIGATION
    FORALL (f: deriv_fun[T], k: nz_deriv_fun[T]):
      derivable?[T](LAMBDA (t): f(t) / k(t));

  % Subtype TCC generated (at line 71, column 37) for  LAMBDA (t): a / k(t)
      % expected type  deriv_fun[T]
  deriv_scald1_lam_TCC1: OBLIGATION
    FORALL (a: real, k: nz_deriv_fun[T]): derivable?[T](LAMBDA (t): a / k(t));

  % Subtype TCC generated (at line 74, column 37) for  LAMBDA (t): f(t) / b
      % expected type  deriv_fun[T]
  deriv_scald2_lam_TCC1: OBLIGATION
    FORALL (b: nzreal, f: deriv_fun[T]): derivable?[T](LAMBDA (t): f(t) / b);


body:
  deriv_domain: THEORY
  BEGIN

    a,b: VAR real

    IMPORTING deriv_domain_def

    deriv_domain_real   : LEMMA deriv_domain?[real]

    deriv_domain_nzreal : LEMMA deriv_domain?[nzreal]

    deriv_domain_posreal: LEMMA deriv_domain?[posreal]

    deriv_domain_nnreal : LEMMA deriv_domain?[nnreal]

    deriv_domain_negreal: LEMMA deriv_domain?[negreal]

    IMPORTING reals@intervals_real

    deriv_domain_open      : LEMMA deriv_domain?[open_interval(a,b)]

    deriv_domain_closed    : LEMMA a /= b IMPLIES deriv_domain?[closed_interval(a,b)]

    deriv_domain_oc        : LEMMA deriv_domain?[{x: real | a < x AND x <= b}]

    deriv_domain_co        : LEMMA deriv_domain?[{x: real | a <= x AND x < b}]

    deriv_domain_posreal_le: LEMMA deriv_domain?[{x: posreal | x <= a}]

    deriv_domain_posreal_lt: LEMMA deriv_domain?[{x: posreal | x < a}]

    deriv_domain_nnreal_lt : LEMMA deriv_domain?[{x: nnreal | x < a}]

  % ------- Not One Element Lemmas

    not_one_element_real   : LEMMA not_one_element?[real]

    not_one_element_nzreal : LEMMA not_one_element?[nzreal]

    not_one_element_posreal: LEMMA not_one_element?[posreal]

    not_one_element_nnreal : LEMMA not_one_element?[nnreal]

    not_one_element_negreal: LEMMA not_one_element?[negreal]

  % ------- Connected Lemmas

    connected_real   : LEMMA connected?[real]

    connected_posreal: LEMMA connected?[posreal]

    connected_nnreal : LEMMA connected?[nnreal]

    connected_negreal: LEMMA not_one_element?[negreal]


  END deriv_domain


body:
  deriv_domains: THEORY
  %-----------------------------------------------------------------------------------------
  %
  %    The derivatives library has been generalized to handle a larger class of domains.
  %    Previously the domain had to be a connected domain defined by the following
  %    predicate:
  %
  %       connected_domain : ASSUMPTION
  %           FORALL (x, y : T), (z : real) :
  %               x <= z AND z <= y IMPLIES T_pred(z)
  %
  %    The following more general domain definition is now used
  %
  %        deriv_domain    : ASSUMPTION FORALL (e: posreal, x:T):
  %                                        EXISTS (y: {u: nzreal | T_pred(u + x)}): abs(y) < e
  %
  %    This definition allows unions of closed and open intervals
  %
  %-----------------------------------------------------------------------------------------
  BEGIN

     IMPORTING deriv_domain

     AUTO_REWRITE+ deriv_domain_real   
     AUTO_REWRITE+ deriv_domain_nzreal 
     AUTO_REWRITE+ deriv_domain_posreal
     AUTO_REWRITE+ deriv_domain_nnreal 
     AUTO_REWRITE+ deriv_domain_negreal
     AUTO_REWRITE+ not_one_element_real
     AUTO_REWRITE+ not_one_element_nzreal 
     AUTO_REWRITE+ not_one_element_posreal
     AUTO_REWRITE+ not_one_element_nnreal 
     AUTO_REWRITE+ not_one_element_negreal

  END deriv_domains


body:
  sqrt_derivative: THEORY
  %------------------------------------------------------------------------------
  %
  % Derivative of sqrt function
  %
  % Author: David Lester (Manchester University)
  %
  %------------------------------------------------------------------------------

  BEGIN

    IMPORTING reals@sq, reals@sqrt, derivatives
  %  IMPORTING derivative_inverse

    sqrt_derivable_fun: AXIOM derivable?[posreal](sqrt)

    deriv_sqrt_fun :  AXIOM deriv[posreal](sqrt)
                               = (LAMBDA (x:posreal): 1/(2*sqrt(x)))

    deriv_sqrt     : AXIOM derivable?[posreal](sqrt) AND
                             deriv[posreal](sqrt)
                                  = (LAMBDA (x:posreal): 1/(2*sqrt(x)))

    sqrt_continuous: LEMMA continuous?[posreal](sqrt)

  END sqrt_derivative

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 24, column 4) for  derivatives[posreal]
      % generated from assumption derivatives.deriv_domain
  sqrt_derivable_fun_TCC1: OBLIGATION deriv_domain?[posreal];

  % Assuming TCC generated (at line 26, column 4) for  derivatives[posreal]
      % generated from assumption derivatives.not_one_element
  sqrt_derivable_fun_TCC2: OBLIGATION not_one_element?[posreal];

  % Subtype TCC generated (at line 17, column 41) for
      % restrict[nonneg_real, posreal, real](sqrt)
      % expected type  deriv_fun[posreal]
  deriv_sqrt_fun_TCC1: OBLIGATION
    derivable?[posreal](restrict[nonneg_real, posreal, real](sqrt));


body:
  composition_continuous [ T1, T2 : TYPE FROM real ] : THEORY
  %----------------------------------------------------------------------------
  %  Composition of continuous functions   
  %
  %  Author:  Bruno Dutertre    Royal Holloway & Bedford New College
  %----------------------------------------------------------------------------
  BEGIN

    IMPORTING continuous_functions, reals@real_fun_props

    f : VAR [T1 -> T2]
    g : VAR [T2 -> real]
    x0 : VAR T1

    F : VAR { E : setof[real] | subset?(E, T1_pred) }  

    composition_cont     : LEMMA continuous?(f, x0) AND continuous?(g, f(x0))
  	                          IMPLIES continuous?(g o f, x0)

    composition_cont_set : AXIOM continuous_on?(f, F) AND continuous_on?(g, Im(f, F))
  	                          IMPLIES continuous_on?(g o f, F)

    composition_cont_fun : LEMMA continuous?(f) AND continuous?(g) 
                                    IMPLIES continuous?(g o f)

  END composition_continuous


body:
  continuous_lambda  [ T : TYPE FROM real ] : THEORY
  BEGIN

    IMPORTING continuous_functions[T],
              reals@min_max, reals@sq
    
    f,g : VAR continuous_fun

    pos_continuous?(f):bool = FORALL (x:T) : f(x) > 0
    pos_continuous_fun : TYPE = (pos_continuous?)

    nzf : VAR nz_continuous_fun
    pf  : VAR pos_continuous_fun
    x   : VAR T
    k   : VAR real
    nzk : VAR nzreal
    n   : VAR nat
    
    id_cont : LEMMA
      continuous?(LAMBDA(x):x)

    const_cont: LEMMA
      continuous?(LAMBDA(x):k)
     
    add_cont : LEMMA
      continuous?(LAMBDA(x):f(x)+g(x))

    sub_cont : LEMMA
      continuous?(LAMBDA(x):f(x)-g(x))

    neg_cont : LEMMA
      continuous?(LAMBDA(x):-f(x))

    mult_cont : LEMMA
      continuous?(LAMBDA(x):f(x)*g(x))

    div_cont : LEMMA
      continuous?(LAMBDA(x):f(x)/nzf(x))

    scal_mult_cont : LEMMA
      continuous?(LAMBDA(x):k*f(x))

    scal_div1_cont : LEMMA
      continuous?(LAMBDA(x):f(x)/nzk)

    scal_div2_cont : LEMMA
      continuous?(LAMBDA(x):k/nzf(x))

    pow_cont : LEMMA
      continuous?(LAMBDA(x):f(x)^n) 

    sq_cont : LEMMA
      continuous?(LAMBDA (x):sq(f(x)))

    IMPORTING sqrt_derivative,
              composition_continuous

    sqrt_cont : LEMMA
      continuous?(LAMBDA(x):sqrt(pf(x)))

    abs_cont : LEMMA
      continuous?(LAMBDA (x):abs(f(x)))

    max_cont : LEMMA
      continuous?(LAMBDA (x):max(f(x),g(x)))

    min_cont : LEMMA
      continuous?(LAMBDA (x):min(f(x),g(x)))

  END continuous_lambda

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 50, column 31) for  n
      % expected type  {i: int | f(x) /= 0 OR i >= 0}
  pow_cont_TCC1: OBLIGATION
    FORALL (f: continuous_fun[T], n: nat, x: T): f(x) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 59, column 31) for  pf(x)
      % expected type  nnx: nonneg_real
  sqrt_cont_TCC1: OBLIGATION
    FORALL (pf: pos_continuous_fun, x: T): pf(x) >= 0;


body:
  continuous_functions_props[ T : TYPE FROM real] : THEORY
  %--------------------------------------------------------
  %  More properties of continuous functions [T1 -> T2]  %
  %  Applications of continuity_interval                 %
  %--------------------------------------------------------
  BEGIN

     ASSUMING

     connected_domain : ASSUMPTION
   	FORALL (x, y : T), (z : real) :
   	    x <= z AND z <= y IMPLIES T_pred(z)

     ENDASSUMING

     IMPORTING % continuity_interval
               continuous_functions,
               reals@real_fun_preds

     f : VAR [T -> real]
     a, b, c, d : VAR T

    % sub_interval : LEMMA
    % 	FORALL (c : T), (d : {x : T | c <= x}), (u : J[c, d]) : T_pred(u)
  	

    %----------------------------------------
    %  Restriction to a sub-interval of T1
    %----------------------------------------

    % R(f, (c : T), (d : {x : T | c <= x})) : [J[c,d] -> real] =
    % 	LAMBDA (u : J[c, d]) : f(u)


    %-----------------------------------------------------
    %  If f is continuous, its restriction is continuous
    %-----------------------------------------------------

    g : VAR { f | continuous?(f) } 

    % continuous_in_subintervals : LEMMA
    % 	a <= b IMPLIES continuous?(R(g, a, b))


    %------------------------------
    %  Intermediate value theorem
    %------------------------------

    x, y, z : VAR real

    intermediate1 : AXIOM a <= b AND g(a) <= x AND x <= g(b) IMPLIES
  	                  EXISTS c : a <= c AND c <= b AND g(c) = x

    intermediate2 : AXIOM a <= b AND g(b) <= x AND x <= g(a) IMPLIES
  	                  EXISTS c : a <= c AND c <= b AND g(c) = x


    %----------------------------------
    %  Max and minimum in an interval
    %----------------------------------

    max_in_interval : AXIOM a <= b IMPLIES
  	                   EXISTS c : a <= c AND c <= b AND 
  		            (FORALL d : a <= d AND d <= b IMPLIES g(d) <= g(c))

    min_in_interval : AXIOM a <= b IMPLIES
  	                   EXISTS c : a <= c AND c <= b AND 
  		            (FORALL d : a <= d AND d <= b IMPLIES g(c) <= g(d))


    %---------------------------------------------------------
    %  Injective, continuous functions are strictly monotone
    %---------------------------------------------------------

    inj_continuous : LEMMA injective?(g) AND a <= b AND b <= c IMPLIES
  	                    (g(a) <= g(b) AND g(b) <= g(c))
  	                    OR (g(c) <= g(b) AND g(b) <= g(a))

    inj_monotone   : LEMMA injective?(g) IFF
  	                    strict_increasing?(g) OR strict_decreasing?(g)

  END continuous_functions_props


body:
  derivative_props [ T : TYPE FROM real ] : THEORY
  BEGIN

    ASSUMING
       IMPORTING deriv_domain_def

       connected_domain : ASSUMPTION connected?[T]

       not_one_element : ASSUMPTION not_one_element?[T]

    ENDASSUMING

    % IMPORTING derivatives_alt[T], continuous_functions_props

     IMPORTING derivatives, continuous_functions_props

  %  AUTO_REWRITE-  abs_0
  %  AUTO_REWRITE-  abs_neg

    deriv_domain: LEMMA deriv_domain?[T]


    f, fp : VAR [T -> real]
    x, y, a, b, c : VAR T
    D : VAR real

    %--------------------------------------

    deriv_maximum : AXIOM
          a < c AND c < b AND derivable?(f, c) AND
          (FORALL x : a < x AND x < b IMPLIES f(x) <= f(c))
      IMPLIES deriv(f, c) = 0


    deriv_minimum : LEMMA
          a < c AND c < b AND derivable?(f, c) AND
          (FORALL x : a < x AND x < b  IMPLIES f(c) <= f(x))
      IMPLIES deriv(f, c) = 0


    %-----------------------
    %  Mean value theorem
    %-----------------------

    mean_value_aux : AXIOM derivable?(f) AND a < b AND f(a) = f(b) IMPLIES
                             EXISTS c : a < c AND c < b AND deriv(f, c) = 0

    mean_value : THEOREM derivable?(f) AND a < b IMPLIES
                             EXISTS c : a < c AND c < b AND 
                                        deriv(f, c) * (b - a) = f(b) - f(a)


    mean_value_abs : AXIOM derivable?(f) AND a /= b IMPLIES  % BUTLER
                             EXISTS c: min(a,b) < c AND c < max(a,b) AND 
                                abs(deriv(f, c)) * abs(b - a) = abs(f(b) - f(a))


    %------------------------------------------
    %  Applications of the mean value theorem
    %------------------------------------------

    g : VAR deriv_fun[T]

    nonneg_derivative : AXIOM increasing?(g) IFF (FORALL x : deriv(g, x) >= 0)

    nonpos_derivative : AXIOM decreasing?(g) IFF (FORALL x : deriv(g, x) <= 0)

    positive_derivative : LEMMA (FORALL x: deriv(g, x) > 0) 
                                    IMPLIES strict_increasing?(g)

    negative_derivative : LEMMA (FORALL x : deriv(g, x) < 0) 
                                    IMPLIES strict_decreasing?(g)

    null_derivative : LEMMA constant?(g) IFF (FORALL x : deriv(g, x) = 0)

  %% --- David Lester Additions ---

    minimum_derivative: LEMMA deriv(g)(x) = 0 AND x /= y AND
                            (FORALL (y:T): y /= x IMPLIES deriv(g)(y)*(y-x) > 0) 
                               IMPLIES g(x) < g(y)

    maximum_derivative: LEMMA deriv(g)(x) = 0 AND x /= y AND
                            (FORALL (y:T): y /= x IMPLIES deriv(g)(y)*(y-x) < 0) 
                               IMPLIES g(y) < g(x)

    strict_minimum_derivative: LEMMA strict_increasing?(deriv(g)) AND 
                                     deriv(g)(x) = 0 AND x /= y
                                        IMPLIES g(x) < g(y)

    strict_maximum_derivative: LEMMA strict_decreasing?(deriv(g)) AND 
                                     deriv(g)(x) = 0 AND x /= y
                                        IMPLIES g(y) < g(x)


  % — moved from derivatives_more

    monotonic_antideriv: LEMMA FORALL (a, b: T, f, g: deriv_fun[T]):
      (FORALL (x:T): deriv(f)(x) >= deriv(g)(x)) AND
      a <= b =>
      f(b) - f(a) >= g(b) - g(a)

    % derivative_alt : LEMMA FORALL (D: real, ff: [T -> real], x: T):
    % 	convergence(NQ(ff, x), 0, D)
    %   IFF convergence(LAMBDA  (y: {yy:T|yy/=x}): (ff(y) - ff(x))/(y - x), x, D)

    % derivative_fun_alt : LEMMA FORALL (ff, gg: [T -> real]):
    % 	derivable?(ff) AND deriv(ff) = gg
    %   IFF (FORALL x: convergence(LAMBDA  (y: {yy:T|yy/=x}):
    %                      (ff(y) - ff(x))/(y - x), x, gg(x)))

    epsi_lt_le: LEMMA (FORALL (epsilon: posreal): x < epsilon) IFF
                 (FORALL (epsilon: posreal): x <= epsilon) 



  END derivative_props

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 30, column 12) for  derivatives_def[T]
      % generated from assumption derivatives_def.deriv_domain
  deriv_maximum_TCC1: OBLIGATION
    FORALL (a, b, c: T): a < c AND c < b IMPLIES deriv_domain?[T];

  % Assuming TCC generated (at line 30, column 12) for  derivatives_def[T]
      % generated from assumption derivatives_def.not_one_element
  deriv_maximum_TCC2: OBLIGATION
    FORALL (a, b, c: T): a < c AND c < b IMPLIES not_one_element?[T];

  % Assuming TCC generated (at line 15, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  mean_value_aux_TCC1: OBLIGATION deriv_domain?[T];

  % Assuming TCC generated (at line 15, column 13) for  derivatives[T]
      % generated from assumption derivatives.not_one_element
  mean_value_aux_TCC2: OBLIGATION not_one_element?[T];

  % Subtype TCC generated (at line 46, column 67) for  c
      % expected type  {x | derivable?[T](f, x)}
  mean_value_aux_TCC3: OBLIGATION
    FORALL (a, b: T, f: [T -> real]):
      f(a) = f(b) AND a < b AND derivable?(f) IMPLIES
       (FORALL (c): c < b AND a < c IMPLIES derivable?[T](f, c));

  % Subtype TCC generated (at line 50, column 47) for  c
      % expected type  {x | derivable?[T](f, x)}
  mean_value_TCC1: OBLIGATION
    FORALL (a, b: T, f: [T -> real]):
      a < b AND derivable?(f) IMPLIES
       (FORALL (c): c < b AND a < c IMPLIES derivable?[T](f, c));

  % Subtype TCC generated (at line 55, column 43) for  c
      % expected type  {x | derivable?[T](f, x)}
  mean_value_abs_TCC1: OBLIGATION
    FORALL (a, b: T, f: [T -> real]):
      a /= b AND derivable?(f) IMPLIES
       (FORALL (c):
          c < max(a, b) AND min(a, b) < c IMPLIES derivable?[T](f, c));

  % Subtype TCC generated (at line 64, column 68) for  x
      % expected type  {x | derivable?[T](g, x)}
  nonneg_derivative_TCC1: OBLIGATION
    FORALL (g: deriv_fun[T], x): derivable?[T](g, x);


body:
  chain_rule [ T1, T2 : TYPE FROM real ] : THEORY
  %----------------------------------------------------------------------------
  %  Author:  Bruno Dutertre    Royal Holloway & Bedford New College
  %----------------------------------------------------------------------------
  BEGIN

    ASSUMING

      IMPORTING deriv_domain_def

       deriv_domain1     : ASSUMPTION deriv_domain?[T1]

       not_one_element1  : ASSUMPTION not_one_element?[T1]

       deriv_domain2     : ASSUMPTION deriv_domain?[T2]

       not_one_element2  : ASSUMPTION not_one_element?[T2]

    ENDASSUMING

    IMPORTING derivative_props % , lim_of_composition

    f : VAR [T1 -> T2]
    g : VAR [T2 -> real]
    x : VAR T1
    DF, DG : VAR real

    % chain_rule_cnvg        : LEMMA convergence(NQ(f, x), 0, DF) AND 
    %                             convergence(NQ(g, f(x)), 0, DG)
    % 	                         IMPLIES convergence(NQ(g o f, x), 0, DG * DF)

    composition_derivable : AXIOM derivable?(f, x) AND derivable?(g, f(x))
  	                           IMPLIES derivable?(g o f, x)

    composition_derivable_fun : LEMMA derivable?(f) AND derivable?(g) 
                                         IMPLIES derivable?(g o f)

    deriv_composition : AXIOM derivable?(f, x) AND derivable?(g, f(x))
  	                 IMPLIES deriv(g o f, x) = deriv(g, f(x)) * deriv(f, x)


    ff : VAR { f | derivable?(f) }
    gg : VAR { g | derivable?(g) }

    deriv_comp_fun     : LEMMA deriv(gg o ff) = (deriv(gg) o ff) * deriv(ff)


    comp_derivable_fun : LEMMA derivable?(f) AND derivable?(g) 
                                         IMPLIES derivable?(LAMBDA (x: T1): g(f(x)))

    chain_rule         : LEMMA deriv(LAMBDA (x: T1): gg(ff(x))) =
                                 (LAMBDA (x: T1): deriv(gg)(ff(x))) * deriv(ff)

  END chain_rule

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 30, column 12) for  derivatives_def[T1]
      % generated from assumption derivatives_def.deriv_domain
  composition_derivable_TCC1: OBLIGATION deriv_domain?[T1];

  % Assuming TCC generated (at line 30, column 12) for  derivatives_def[T1]
      % generated from assumption derivatives_def.not_one_element
  composition_derivable_TCC2: OBLIGATION not_one_element?[T1];

  % Assuming TCC generated (at line 30, column 12) for  derivatives_def[T2]
      % generated from assumption derivatives_def.deriv_domain
  composition_derivable_TCC3: OBLIGATION
    FORALL (f: [T1 -> T2], x: T1): derivable?(f, x) IMPLIES deriv_domain?[T2];

  % Assuming TCC generated (at line 30, column 12) for  derivatives_def[T2]
      % generated from assumption derivatives_def.not_one_element
  composition_derivable_TCC4: OBLIGATION
    FORALL (f: [T1 -> T2], x: T1):
      derivable?(f, x) IMPLIES not_one_element?[T2];

  % Assuming TCC generated (at line 15, column 13) for  derivatives[T2]
      % generated from assumption derivatives.deriv_domain
  composition_derivable_fun_TCC1: OBLIGATION
    FORALL (f: [T1 -> T2]): derivable?(f) IMPLIES deriv_domain?[T2];

  % Assuming TCC generated (at line 15, column 13) for  derivatives[T2]
      % generated from assumption derivatives.not_one_element
  composition_derivable_fun_TCC2: OBLIGATION
    FORALL (f: [T1 -> T2]): derivable?(f) IMPLIES not_one_element?[T2];

  % Subtype TCC generated (at line 39, column 39) for  x
      % expected type  {x | derivable?[T1](g o f, x)}
  deriv_composition_TCC1: OBLIGATION
    FORALL (f: [T1 -> T2], g: [T2 -> real], x: T1):
      derivable?(g, f(x)) AND derivable?(f, x) IMPLIES
       derivable?[T1](o[T1, T2, real](g, f), x);

  % Assuming TCC generated (at line 15, column 13) for  derivatives[T2]
      % generated from assumption derivatives.deriv_domain
  gg_TCC1: OBLIGATION deriv_domain?[T2];

  % Assuming TCC generated (at line 15, column 13) for  derivatives[T2]
      % generated from assumption derivatives.not_one_element
  gg_TCC2: OBLIGATION not_one_element?[T2];

  % Subtype TCC generated (at line 45, column 35) for  gg o ff
      % expected type  deriv_fun[T1]
  deriv_comp_fun_TCC1: OBLIGATION
    FORALL (ff: {f | derivable?(f)}, gg: {g | derivable?(g)}):
      derivable?[T1](o[T1, T2, real](gg, ff));

  % Subtype TCC generated (at line 51, column 35) for
      % LAMBDA (x: T1): gg(ff(x))
      % expected type  deriv_fun[T1]
  chain_rule_TCC1: OBLIGATION
    FORALL (ff: {f | derivable?(f)}, gg: {g | derivable?(g)}):
      derivable?[T1](LAMBDA (x: T1): gg(ff(x)));


body:
  nth_derivatives[T: TYPE FROM real]: THEORY
  %------------------------------------------------------------------------------
  % The nth_derivatives theory defines the nth derivative of a function
  %
  % Developed  by Ricky W. Butler      NASA Langley Research Center
  %               David Lester         Manchester University
  % 
  %      Version 1.0    last modified 10/30/00
  %      Version 1.1    Generalised for an arbitrary interval: T DRL 27/10/03
  %  
  %------------------------------------------------------------------------------
  BEGIN

     ASSUMING

  %    connected_domain : ASSUMPTION
  %         FORALL (x, y : T), (z : real) :
  %             x <= z AND z <= y IMPLIES T_pred(z)

     IMPORTING deriv_domain_def

     deriv_domain    : ASSUMPTION deriv_domain?[T]

     not_one_element : ASSUMPTION not_one_element?[T]

     ENDASSUMING

     IMPORTING derivatives

     f: VAR [T -> real]
     m, n: VAR nat

     derivable_n_times?(f,n): RECURSIVE bool =
                                  IF n = 0 THEN TRUE
                                  ELSE
                                     derivable?(f) AND
                                     derivable_n_times?(deriv(f),n-1)
                                  ENDIF MEASURE n


     derivable_n_times_lem: LEMMA derivable_n_times?(f,n) AND m <= n IMPLIES
                                     derivable_n_times?(f,m) 


     derivable_n_times_def: LEMMA derivable_n_times?(f, n+1) IMPLIES
                                    derivable_n_times?(deriv(f), n)



     nderiv_fun(n: nat): TYPE = {g: [T -> real] | derivable_n_times?(g,n)}


     nderiv(n: nat,f:nderiv_fun(n)):RECURSIVE [T -> real] = 
                   IF n = 0 THEN f
                   ELSE
                      nderiv(n-1,deriv(f))
                   ENDIF MEASURE n


     nderiv_derivable: LEMMA m <= n AND derivable_n_times?(f, 1 + n)
                               IMPLIES derivable?(nderiv(m, f))

     nderiv_derivable_aux: LEMMA derivable_n_times?(f, n+1) IMPLIES
                                 nderiv(n+1,f) = deriv(nderiv(n,f))

     nderiv_derivable_eqv: LEMMA derivable_n_times?(f, 1 + n) IFF
                               derivable_n_times?(f,n) AND derivable?(nderiv(n, f))


  END nth_derivatives

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 28, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  derivable_n_times?_TCC1: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES deriv_domain?[T];

  % Assuming TCC generated (at line 28, column 13) for  derivatives[T]
      % generated from assumption derivatives.not_one_element
  derivable_n_times?_TCC2: OBLIGATION
    FORALL (n: nat): NOT n = 0 IMPLIES not_one_element?[T];

  % Subtype TCC generated (at line 37, column 63) for  n - 1
      % expected type  nat
  derivable_n_times?_TCC3: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable?(f) AND NOT n = 0 IMPLIES n - 1 >= 0;

  % Termination TCC generated (at line 37, column 35) for
      % derivable_n_times?(deriv(f), n - 1)
  derivable_n_times?_TCC4: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable?(f) AND NOT n = 0 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 46, column 59) for  f
      % expected type  deriv_fun[T]
  derivable_n_times_def_TCC1: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES derivable?[T](f);

  % Assuming TCC generated (at line 28, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  derivable_n_times_def_TCC2: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES deriv_domain?[T];

  % Assuming TCC generated (at line 28, column 13) for  derivatives[T]
      % generated from assumption derivatives.not_one_element
  derivable_n_times_def_TCC3: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES not_one_element?[T];

  % Subtype TCC generated (at line 56, column 27) for  n - 1
      % expected type  nat
  nderiv_TCC1: OBLIGATION
    FORALL (n: nat, f: nderiv_fun(n)): NOT n = 0 IMPLIES n - 1 >= 0;

  % Subtype TCC generated (at line 56, column 37) for  f
      % expected type  deriv_fun[T]
  nderiv_TCC2: OBLIGATION
    FORALL (n: nat, f: nderiv_fun(n)): NOT n = 0 IMPLIES derivable?[T](f);

  % Subtype TCC generated (at line 56, column 31) for  deriv(f)
      % expected type  nderiv_fun(n - 1)
  nderiv_TCC3: OBLIGATION
    FORALL (n: nat, f: nderiv_fun(n)):
      NOT n = 0 IMPLIES derivable_n_times?(deriv[T](f), n - 1);

  % Termination TCC generated (at line 56, column 20) for
      % nderiv(n - 1, deriv(f))
  nderiv_TCC4: OBLIGATION
    FORALL (n: nat, f: nderiv_fun(n)): NOT n = 0 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 61, column 58) for  f
      % expected type  nderiv_fun(m)
  nderiv_derivable_TCC1: OBLIGATION
    FORALL (f: [T -> real], m, n: nat):
      derivable_n_times?(f, 1 + n) AND m <= n IMPLIES
       derivable_n_times?(f, m);

  % Assuming TCC generated (at line 28, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  nderiv_derivable_TCC2: OBLIGATION
    FORALL (f: [T -> real], m, n: nat):
      derivable_n_times?(f, 1 + n) AND m <= n IMPLIES deriv_domain?[T];

  % Assuming TCC generated (at line 28, column 13) for  derivatives[T]
      % generated from assumption derivatives.not_one_element
  nderiv_derivable_TCC3: OBLIGATION
    FORALL (f: [T -> real], m, n: nat):
      derivable_n_times?(f, 1 + n) AND m <= n IMPLIES not_one_element?[T];

  % Subtype TCC generated (at line 64, column 42) for  f
      % expected type  nderiv_fun(1 + n)
  nderiv_derivable_aux_TCC1: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES derivable_n_times?(f, 1 + n);

  % Subtype TCC generated (at line 64, column 62) for  f
      % expected type  nderiv_fun(n)
  nderiv_derivable_aux_TCC2: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES derivable_n_times?(f, n);

  % Subtype TCC generated (at line 64, column 53) for  nderiv(n, f)
      % expected type  deriv_fun[T]
  nderiv_derivable_aux_TCC3: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES derivable?[T](nderiv(n, f));

  % Assuming TCC generated (at line 28, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  nderiv_derivable_eqv_TCC1: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n) IMPLIES deriv_domain?[T];

  % Assuming TCC generated (at line 28, column 13) for  derivatives[T]
      % generated from assumption derivatives.not_one_element
  nderiv_derivable_eqv_TCC2: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n) IMPLIES not_one_element?[T];


body:
  taylors[T: TYPE FROM real]: THEORY
  %------------------------------------------------------------------------------
  % The Taylors theory establishes Taylor's Theorem (Rosenlicht Page 107)
  %
  %
  % Developed  by Ricky W. Butler      NASA Langley Research Center
  %               David Lester         Manchester University
  % 
  %      Version 1.0    last modified 10/30/00
  %      version 1.1    Generalised for arbitrary interval T (DRL) 27/10/03
  %   
  %------------------------------------------------------------------------------

  BEGIN

     ASSUMING
       IMPORTING deriv_domain_def

       connected_domain : ASSUMPTION connected?[T]
   
       not_one_element : ASSUMPTION not_one_element?[T]
   
     ENDASSUMING

     deriv_domain: LEMMA deriv_domain?[T]
     IMPORTING reals@sigma_nat, ints@factorial
     IMPORTING derivatives, nth_derivatives 
     IMPORTING derivative_props % need mean value theorem




     f:            VAR [T -> real]
     m, n, nn, ii: VAR nat
     x,xx,aa,bb:   VAR T
     Rn: VAR [T -> real]


  %   fn: VAR [nat -> real]
  %   nn: VAR negint
  %   sigma_0_neg: LEMMA sigma(0,nn,fn) = 0
     AUTO_REWRITE+ sigma_0_neg


     sigma_derivable: LEMMA  FORALL (g: [T,nat -> real]):
                     (FORALL (ii: subrange(0,n)):
                            derivable?(LAMBDA aa: g(aa,ii))) IMPLIES
            derivable?[T](LAMBDA aa: sigma(0, n, (LAMBDA m: g(aa,m))))


     tay1: LEMMA derivable?((LAMBDA x: (bb - x) ^ n / factorial(n)))

     tay2: LEMMA derivable?(LAMBDA x: (bb - x)) AND 
                 deriv(LAMBDA x: (bb - x)) = const_fun(-1)

     tay3: LEMMA derivable?(LAMBDA x: (bb - x) ^ (n+1)/factorial(n+1)) AND
                 deriv(LAMBDA x: (bb - x) ^ (n+1)/factorial(n+1)) =
                        - (LAMBDA x: (bb - x) ^ n/factorial(n))

     deriv_sigma: LEMMA FORALL (FF: [T,nat -> real]): 
                (FORALL (ii: subrange(0,n)): derivable?(LAMBDA xx: FF(xx,ii)))
                  IMPLIES
                        deriv(LAMBDA x: sigma(0,n,(LAMBDA n: FF(x,n)))) =
           (LAMBDA x: sigma(0,n,(LAMBDA ii: IF ii > n THEN 0 
                                            ELSE deriv(LAMBDA xx: FF(xx,ii))(x)
                                            ENDIF)))
     
     nderiv_term_derivable: LEMMA derivable_n_times?(f,n+1) IMPLIES
                     derivable?(LAMBDA (aa: T): 
                      IF n = 0 THEN f(aa) ELSE
                         nderiv(n, f)(aa) * (bb-aa)^n / factorial(n)
                      ENDIF)

     taylor_derivable: LEMMA derivable_n_times?(f,n+1) IMPLIES
            derivable?(LAMBDA aa: f(bb) -
                sigma(0, n,  LAMBDA nn:
                        IF nn > n  THEN 0
                        ELSIF nn = 0 THEN f(aa)
                        ELSE nderiv(nn,f)(aa) * (bb - aa)^nn / factorial(nn)
                        ENDIF))

     deriv_nderiv: LEMMA  derivable_n_times?(f, n+1) IMPLIES
                        deriv((LAMBDA xx: (nderiv(n, f)(xx)))) = nderiv(n+1, f)

     term_by_term_deriv: LEMMA derivable_n_times?(f, 1 + n) IMPLIES
          sigma(0, n,
                 LAMBDA ii: IF ii > n THEN 0
                          ELSE deriv(LAMBDA xx: IF ii = 0 THEN f(xx) ELSE
                                           nderiv(ii, f)(xx) * (bb - xx) ^ ii /
                                                     factorial(ii) ENDIF) (x)
                          ENDIF)
                            = nderiv(1 + n, f)(x) * (bb - x) ^ n / factorial(n)



     taylor_lemma: LEMMA derivable_n_times?(f,n+1) AND 
                         Rn = (LAMBDA aa: f(bb) - 
                            sigma(0,n,(LAMBDA nn: IF nn > n THEN 0 
                              ELSIF nn = 0 THEN f(aa)
                              ELSE
                               nderiv(nn,f)(aa)*(bb-aa)^nn/factorial(nn) ENDIF)))
               IMPLIES
                  deriv(Rn) = (LAMBDA x: -nderiv(n+1,f)(x)*(bb-x)^n/factorial(n))

     between(aa,bb): TYPE = {x: T | (aa < bb IMPLIES aa < x AND x < bb) AND
                                    (bb < aa  IMPLIES bb < x AND x < aa) AND
                                    (aa = bb IMPLIES x = aa)}

  %  Note: if aa /= bb then between(aa,bb) is Open_interval(aa,bb) 

     Taylors: THEOREM derivable_n_times?(f,n+1) IMPLIES
                 (EXISTS (c: between(aa,bb)): 
                 f(bb) = sigma(0,n,(LAMBDA nn: IF nn > n THEN 0 
                                               ELSIF nn = 0 THEN f(aa) ELSE
                              nderiv(nn,f)(aa)*(bb-aa)^nn/factorial(nn) ENDIF))
                           + nderiv(n+1,f)(c)*(bb-aa)^(n+1)/factorial(n+1))


     Taylor_rem(n:nat,f:nderiv_fun[T](n+1),aa,bb,(c:between(aa,bb))): real = 
                nderiv(n+1,f)(c)*(bb-aa)^(n+1)/factorial(n+1)


  %  --------- Infinitely Derivable Functions ---------

     inf_deriv_fun?(f): bool = (FORALL n: derivable_n_times?(f,n))

     Taylor_term(f:(inf_deriv_fun?),aa,bb)(n): real = 
                                     IF n = 0 THEN f(aa) ELSE
                                       nderiv(n,f)(aa)*(bb-aa)^n/factorial(n) 
                                     ENDIF

     Taylors_inf: THEOREM inf_deriv_fun?(f) IMPLIES
                          (EXISTS (c: between(aa,bb)): 
                             f(bb) = sigma(0,n,Taylor_term(f,aa,bb))
                                           + Taylor_rem(n,f,aa,bb,c))

  END taylors

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 27, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  sigma_derivable_TCC1: OBLIGATION
    FORALL (n: nat, ii: subrange(0, n)): deriv_domain?[T];

  % Assuming TCC generated (at line 27, column 13) for  derivatives[T]
      % generated from assumption derivatives.not_one_element
  sigma_derivable_TCC2: OBLIGATION
    FORALL (n: nat, ii: subrange(0, n)): not_one_element?[T];

  % Subtype TCC generated (at line 48, column 44) for  n
      % expected type  T_high[nat]
  sigma_derivable_TCC3: OBLIGATION
    FORALL (n: nat, g: [T, nat -> real]):
      (FORALL (ii: subrange(0, n)): derivable?(LAMBDA aa: g(aa, ii))) IMPLIES
       (FORALL (aa1): n >= 0 OR (EXISTS (j: nat): n <= j));

  % Subtype TCC generated (at line 51, column 48) for  n
      % expected type  {i: int | (bb - x) /= 0 OR i >= 0}
  tay1_TCC1: OBLIGATION FORALL (bb: T, n: nat, x): (bb - x) /= 0 OR n >= 0;

  % Subtype TCC generated (at line 56, column 48) for  (n + 1)
      % expected type  {i: int | (bb - x) /= 0 OR i >= 0}
  tay3_TCC1: OBLIGATION
    FORALL (bb: T, n: nat, x): (bb - x) /= 0 OR (n + 1) >= 0;

  % Subtype TCC generated (at line 63, column 28) for
      % LAMBDA x: sigma(0, n, (LAMBDA n: FF(x, n)))
      % expected type  deriv_fun[T]
  deriv_sigma_TCC1: OBLIGATION
    FORALL (n1: nat, FF: [T, nat -> real]):
      (FORALL (ii: subrange(0, n1)): derivable?(LAMBDA xx: FF(xx, ii)))
       IMPLIES
       derivable?[T](LAMBDA x: sigma[nat](0, n1, (LAMBDA n: FF(x, n))));

  % Subtype TCC generated (at line 65, column 53) for  LAMBDA xx: FF(xx, ii)
      % expected type  deriv_fun[T]
  deriv_sigma_TCC2: OBLIGATION
    FORALL (n: nat, FF: [T, nat -> real]):
      (FORALL (ii: subrange(0, n)): derivable?(LAMBDA xx: FF(xx, ii)))
       IMPLIES
       (FORALL (x, ii1):
          NOT ii1 > n IMPLIES derivable?[T](LAMBDA xx: FF(xx, ii1)));

  % Subtype TCC generated (at line 71, column 33) for  f
      % expected type  nderiv_fun[T](n)
  nderiv_term_derivable_TCC1: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES
       (FORALL (aa: T): NOT n = 0 IMPLIES derivable_n_times?[T](f, n));

  % Subtype TCC generated (at line 76, column 23) for  n
      % expected type  T_high[nat]
  taylor_derivable_TCC1: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES
       (FORALL (aa): n >= 0 OR (EXISTS (j: nat): n <= j));

  % Subtype TCC generated (at line 79, column 37) for  f
      % expected type  nderiv_fun[T](nn)
  taylor_derivable_TCC2: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES
       (FORALL (aa, nn):
          NOT nn = 0 AND NOT nn > n IMPLIES derivable_n_times?[T](f, nn));

  % Subtype TCC generated (at line 79, column 56) for  nn
      % expected type  {i: int | (bb - aa) /= 0 OR i >= 0}
  taylor_derivable_TCC3: OBLIGATION
    FORALL (bb: T, f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES
       (FORALL (aa, nn):
          NOT nn = 0 AND NOT nn > n IMPLIES (bb - aa) /= 0 OR nn >= 0);

  % Subtype TCC generated (at line 83, column 51) for  f
      % expected type  nderiv_fun[T](n)
  deriv_nderiv_TCC1: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES
       (FORALL (xx): derivable_n_times?[T](f, n));

  % Subtype TCC generated (at line 83, column 29) for
      % (LAMBDA xx: (nderiv(n, f)(xx)))
      % expected type  deriv_fun[T]
  deriv_nderiv_TCC2: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES
       derivable?[T](LAMBDA xx: (nderiv[T](n, f)(xx)));

  % Subtype TCC generated (at line 83, column 75) for  f
      % expected type  nderiv_fun[T](1 + n)
  deriv_nderiv_TCC3: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, n + 1) IMPLIES derivable_n_times?[T](f, 1 + n);

  % Subtype TCC generated (at line 86, column 17) for  n
      % expected type  T_high[nat]
  term_by_term_deriv_TCC1: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, 1 + n) IMPLIES
       n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 89, column 52) for  f
      % expected type  nderiv_fun[T](ii)
  term_by_term_deriv_TCC2: OBLIGATION
    FORALL (f: [T -> real], n: nat):
      derivable_n_times?(f, 1 + n) IMPLIES
       (FORALL (ii):
          NOT ii > n IMPLIES
           (FORALL (xx): NOT ii = 0 IMPLIES derivable_n_times?[T](f, ii)));

  % Subtype TCC generated (at line 89, column 73) for  ii
      % expected type  {i: int | (bb - xx) /= 0 OR i >= 0}
  term_by_term_deriv_TCC3: OBLIGATION
    FORALL (bb: T, f: [T -> real], n: nat):
      derivable_n_times?(f, 1 + n) IMPLIES
       (FORALL (ii):
          NOT ii > n IMPLIES
           (FORALL (xx): NOT ii = 0 IMPLIES (bb - xx) /= 0 OR ii >= 0));

  % Subtype TCC generated (at line 88, column 35) for
      % LAMBDA xx:
      %   IF ii = 0 THEN f(xx)
      %   ELSE nderiv(ii, f)(xx) * (bb - xx) ^ ii / factorial(ii)
      %   ENDIF
      % expected type  deriv_fun[T]
  term_by_term_deriv_TCC4: OBLIGATION
    FORALL (bb: T, f: [T -> real], n: nat):
      derivable_n_times?(f, 1 + n) IMPLIES
       (FORALL (ii):
          NOT ii > n IMPLIES
           derivable?[T]
               (LAMBDA xx:
                  IF ii = 0 THEN f(xx)
                  ELSE nderiv[T](ii, f)(xx) * (bb - xx) ^ ii / factorial(ii)
                  ENDIF));

  % Subtype TCC generated (at line 103, column 22) for  Rn
      % expected type  deriv_fun[T]
  taylor_lemma_TCC1: OBLIGATION
    FORALL (Rn: [T -> real], bb: T, f: [T -> real], n: nat):
      (Rn =
        (LAMBDA aa:
           f(bb) -
            sigma(0, n,
                  LAMBDA nn:
                    IF nn > n THEN 0
                    ELSIF nn = 0 THEN f(aa)
                    ELSE nderiv(nn, f)(aa) * (bb - aa) ^ nn / factorial(nn)
                    ENDIF)))
       AND derivable_n_times?(f, n + 1)
       IMPLIES derivable?[T](Rn);

  % Subtype TCC generated (at line 129, column 46) for  f
      % expected type  nderiv_fun[T](n)
  Taylor_term_TCC1: OBLIGATION
    FORALL (f: (inf_deriv_fun?), aa: T, bb: T, n: nat):
      NOT n = 0 IMPLIES derivable_n_times?[T](f, n);

  % Subtype TCC generated (at line 134, column 43) for  n
      % expected type  T_high[nat]
  Taylors_inf_TCC1: OBLIGATION
    FORALL (aa, bb: T, f: [T -> real], n: nat):
      inf_deriv_fun?(f) IMPLIES
       (FORALL (c: between(aa, bb)): n >= 0 OR (EXISTS (j: nat): n <= j));

  % Subtype TCC generated (at line 135, column 56) for  f
      % expected type  nderiv_fun[T](1 + n)
  Taylors_inf_TCC2: OBLIGATION
    FORALL (aa, bb: T, f: [T -> real], n: nat):
      inf_deriv_fun?(f) IMPLIES
       (FORALL (c: between(aa, bb)): derivable_n_times?[T](f, 1 + n));


body:
  integral_def[T: TYPE FROM real]: THEORY
  %----------------------------------------------------------------------------
  %
  %    Definition of Riemann Integral
  %    Author: Rick Butler
  %    Major Revision:  12/1/03
  %
  %----------------------------------------------------------------------------
  BEGIN

     ASSUMING
        IMPORTING deriv_domain_def[T]

        connected_domain : ASSUMPTION connected?[T]


        not_one_element : ASSUMPTION not_one_element?[T]

     ENDASSUMING


     IMPORTING finite_sets@finite_sets_minmax[real,<=] %, finite_sets_more

     AUTO_REWRITE+ finseq_appl

     a,b,x: VAR T
     f,g: VAR [T -> real]

  %   open_interval  (a:T,b:{x:T|a<x}): TYPE = { x | a <  x AND x <  b}
  %   closed_interval(a:T,b:{x:T|a<x}): TYPE = { x | a <= x AND x <= b}

     IMPORTING reals@intervals_real[T]

  % % Unlike Rosenlicht index runs from 0 to N-1:

  %    partition(a:T,b:{x:T|a<x}): TYPE = 
  %               {fs: finite_sequence[closed_interval(a,b)] | 
  %                     Let N = length(fs), xx = seq(fs) IN
  %                     N > 1 AND xx(0) = a AND xx(N-1) = b AND
  %                     (FORALL (ii: below(N-1)): xx(ii) < xx(ii+1))}

  %    width(a:T, b:{x:T|a<x}, P: partition(a,b)): posreal =
  %              LET xx = seq(P), N = length(P) IN
  %                       max({ l: real | EXISTS (ii: below(N-1)):
  %                                          l = xx(ii+1) - xx(ii)}) 

  %    width_lem     : LEMMA (FORALL (a:T), (b:{x:T|a<x}),
  %                             (P: partition(a,b)),(ii: below(length(P)-1)):
  %                          width(a,b,P) >= P(ii+1) - P(ii))

  %    parts_order   : LEMMA  FORALL (P: partition(a,b), ii,jj: below(length(P))):
  %                               ii < jj IMPLIES seq(P)(ii) < seq(P)(jj)


  %    parts_order_le: LEMMA FORALL (P: partition(a,b),ii,jj: below(length(P))):
  %                              ii <= jj IMPLIES seq(P)(ii) <= seq(P)(jj)


     
  %    parts_disjoint: LEMMA FORALL (P: partition(a,b), ii,jj: below(length(P)-1)):
  %                              seq(P)(ii) < x AND x < seq(P)(1 + ii) AND
  %                              seq(P)(jj) < x AND x < seq(P)(1 + jj)
  %                              IMPLIES
  %                                 jj = ii

  %    in_part?(a:T, b:{x:T|a<x},P: partition(a,b),xx:T): MACRO bool = 
  %                         EXISTS (ii: below(length(P)-1)): xx = seq(P)(ii)

  %    in_sect?(a:T, b:{x:T|a<x},P: partition(a,b),
  %             ii: below(length(P)-1),xx:T): MACRO bool = 
  %                       seq(P)(ii) < xx AND xx < seq(P)(ii+1)


  %    part_in       : LEMMA FORALL (P: partition(a,b)):    
  %                              a < b AND a <= x AND x <= b IMPLIES
  %                                  (EXISTS (ii: below(length(P)-1)): 
  %                                        seq(P)(ii) <= x AND x <= seq(P)(ii+1))

  %    part_not_in       : LEMMA a < b IMPLIES FORALL (P: partition(a,b)):    
  %                                 FORALL (ii,jj: below(length(P)-1)): 
  %                                   seq(P)(ii) < x AND x < seq(P)(ii+1) 
  %                                 IMPLIES x /= seq(P)(jj)

  %    Prop: VAR [T -> bool]
  %    part_induction: LEMMA  (FORALL (P: partition(a,b)): 
  %                               (FORALL ( x: closed_interval(a,b)):
  %                            LET xx = seq(P), N = length(P) IN 
  %                    (FORALL (ii : below(N-1)):
  %                            xx(ii) <= x AND x <= xx(ii+1) IMPLIES
  %                                 Prop(x))
  %                   IMPLIES Prop(x) ) )


  %    IMPORTING reals@sigma_below, reals@sigma_upto

  %    eq_partition(a:T,b:{x:T|a<x},N: above(1)): partition(a,b) =
  %                   (# length := N,
  %                      seq := (LAMBDA (ii: below(N)): a + ii*(b-a)/(N-1)) #)


  %    xis?(a:T,b:{x:T|a<x},P:partition(a,b))
  %          (fs: [below(length(P)-1) -> closed_interval(a,b)]): bool = 
  %               (FORALL (ii: below(length(P)-1)): 
  %                      P(ii) <= fs(ii) AND fs(ii) <= P(ii+1))


  %    AUTO_REWRITE+ xis?


  %    xis_lem: LEMMA FORALL (P: partition(a,b), (xis: (xis?(a,b,P))),
  %                          (ii: below(length(P)-1))):
  %                          P(ii) <= xis(ii) AND xis(ii) <= P(ii+1)


  %    AUTO_REWRITE+ xis_lem



  %    Rie_sum(a:T,b:{x:T|a<x},P:partition(a,b),
  %                   xis: (xis?(a,b,P)),f:[T->real]): real =
  %                   LET N = length(P)-1 IN
  %           sigma[below(N)](0,N-1,(LAMBDA (n: below(N)):
  %                                        (P(n+1) - P(n)) * f(xis(n))))


  %    Rie_sec(a:T,b:{x:T|a<x},P:partition(a,b), xis: (xis?(a,b,P)), f:[T->real], 
  %            n: upto(length(P)-1)): real = 
  %                            IF n = 0 THEN 0
  %                            ELSE (seq(P)(n) - seq(P)(n - 1)) * f(xis(n-1)) 
  %                            ENDIF

  %    Rie_sum_alt(a:T,b:{x:T|a<x},P:partition(a,b),
  %                   xis: (xis?(a,b,P)),f:[T->real]): real =
  %                   LET N = length(P)-1 IN
  %                      sigma[upto(N)](1,N,(LAMBDA (n: upto(N)): 
  %                             Rie_sec(a,b,P,xis,f,n)))

  %    Rie_sum_alt_lem: LEMMA a < b IMPLIES
  %                             FORALL (P: partition(a,b), (xis: (xis?(a,b,P)))):
  %                                Rie_sum(a,b,P,xis,f) = Rie_sum_alt(a,b,P,xis,f) 



  %    Riemann_sum?(a:T,b:{x:T|a<x},P:partition(a,b),f:[T->real])(S:real): bool =
  %      (EXISTS (xis: (xis?(a,b,P))): LET N = length(P)-1 IN
  %            S = Rie_sum(a,b,P,xis,f))
                             

      integral?(a:T,b:{x:T|a<x},f:[T->real],S:real): bool % = 
     %               (FORALL (epsi: posreal): (EXISTS (delta: posreal):
     %                  (FORALL (P: partition(a,b)):
     %                      width(a,b,P) < delta IMPLIES
     %                         (FORALL (R: (Riemann_sum?(a,b,P,f))):
     %                              abs(S - R) < epsi))))


     % x_in(aa:T,bb:{x:T|aa<x}): {t: T | aa <= t AND t <= bb}

     % pick_one(a:T,b:{x:T|a<x},P: partition(a,b))(ii: below(length(P)-1)): real =
     %                             x_in(P(ii), P(ii+1)) 


     % gen_xis(a:T,b:{x:T|a<x},P: partition(a,b)): (xis?(a,b,P)) = 
     %                                   (# length := length(P) - 1,
     %                                      seq :=  pick_one(a,b,P)
     %                                    #)


     % N: VAR above(1)

     % len_eq_part  : LEMMA a < b IMPLIES length(eq_partition(a,b,N)) = N 
     % eq_part_lem_a: LEMMA a < b IMPLIES seq(eq_partition(a,b,N))(0) = a 
     % eq_part_lem_b: LEMMA a < b IMPLIES seq(eq_partition(a,b,N))(N-1) = b

     % width_eq_part: LEMMA a < b IMPLIES 
     %                          width(a,b,eq_partition(a,b,N)) = (b-a)/(N-1)


     % delta: VAR posreal
     % N_from_delta: LEMMA a < b IMPLIES
     %                        LET N = 2 + floor((b - a) / delta),
     %                            EP = eq_partition(a, b, N) IN
     %                        width(a, b, EP) < delta


     % Riemann?_Rie: LEMMA a < b IMPLIES FORALL (P: partition(a,b),
     %                                           xis: (xis?(a,b,P))): 
     %                             Riemann_sum?(a,b,P,f)(Rie_sum(a,b,P,xis,f)) 


     % AUTO_REWRITE+ Riemann?_Rie

     % A1, A2: VAR real
     % integral_unique: LEMMA a < b AND integral?(a,b,f,A1) AND
     %                           integral?(a,b,f,A2) IMPLIES A1 = A2


      integrable?(a:T,b:{x:T|a<x},f:[T->real]): bool = 
                        (EXISTS (S: real): integral?(a,b,f,S))

      integral(a:T,b:{x:T|a<x}, ff: { f | integrable?(a,b,f)} ):
                       {S: real | integral?(a,b,ff,S)}


     % s: VAR real
     % integral_def: LEMMA a < b IMPLIES  
     %                 ( (integrable?(a,b,f) AND integral(a,b,f) = s)
     %                        IFF integral?(a,b,f,s) )


      integral_restrict_eq: AXIOM a < b AND
                                   (FORALL x: a <= x AND x <= b IMPLIES
                                             f(x) = g(x)) AND
                                  integrable?(a,b,f)
                             IMPLIES integrable?(a,b,g) AND
                                      integral(a,b,g) = integral(a,b,f)


     Integrable?(a:T,b:T,f:[T->real]): bool % = (a = b) OR
    %                               (a < b AND integrable?(a,b,f)) OR
    %                               (b < a  AND integrable?(b,a,f))


     Integrable_funs(a,b): TYPE = { f | Integrable?(a,b,f)} 
   
     % Integral?(a:T,b:T,f:[T->real],S:real): bool = (a = b AND S = 0) OR
     %                             (a < b AND integral?(a,b,f,S))
                                
    
     Integral(a:T,b:T,f:Integrable_funs(a,b)): real % =
  %                     			  IF a = b THEN 0
  %                     			  ELSIF a < b THEN integral(a,b,f)
  %                     			  ELSE -integral(b,a,f)
  %                    			  ENDIF                

     Integrable?_rew   : AXIOM a < b AND Integrable?(a,b,f) IMPLIES integrable?(a,b,f)
     Integral_rew      : AXIOM a < b AND Integrable?(a,b,f) IMPLIES Integral(a,b,f) = integral(a,b,f)


  END integral_def

addendum:
  %%% ================ Addendum: generated declarations ================

  % Existence TCC generated (at line 201, column 4) for
      % integral(a: T, b: {x: T | a < x}, ff: {f | integrable?(a, b, f)}):
      %       {S: real | integral?(a, b, ff, S)}
  integral_TCC1: OBLIGATION
    EXISTS (x1:
              [d: [a: T, b: {x: T | a < x}, {f | integrable?(a, b, f)}] ->
                 {S: real | integral?(d`1, d`2, d`3, S)}]):
      TRUE;

  % Subtype TCC generated (at line 237, column 97) for  f
      % expected type  {f | integrable?(a, b, f)}
  Integral_rew_TCC1: OBLIGATION
    FORALL (a, b: T, f: [T -> real]):
      Integrable?(a, b, f) AND a < b IMPLIES integrable?(a, b, f);


body:
  integral[T: TYPE+ FROM real]: THEORY
  %------------------------------------------------------------------------------
  %
  %  Theory and proofs taken from Introduction to Analysis (Maxwell Rosenlight)
  %
  %  This theory provides the basic properties of the Riemann Integral
  %
  %  Author:  Rick Butler               NASA Langley
  %
  %------------------------------------------------------------------------------

  BEGIN

     ASSUMING
        IMPORTING deriv_domain_def[T]

        connected_domain : ASSUMPTION connected?[T]


        not_one_element : ASSUMPTION not_one_element?[T]

     ENDASSUMING

     IMPORTING integral_def[T],
               derivatives,
               reals@real_fun_ops




     a,b,c,x,y: VAR T
     D,m,M,yv: VAR real
     f,g: VAR [T -> real]


  %    Closed_interval(a:T,b:{x:T | x /= a}): TYPE = {x: T | (a < b IMPLIES 
  %                                                  (a <= x AND x <= b)) AND
  %                                                  (b < a IMPLIES 
  %                                                  (b <= x AND x <= a))}

  %    Closed_interval(a,b:T): TYPE = {x: T | (a <= b IMPLIES 
  %                                                  (a <= x AND x <= b)) AND
  %                                                  (b < a IMPLIES 
  %                                                  (b <= x AND x <= a))}

     Integrable?_a_to_a: AXIOM Integrable?(a,a,f) 
     Integral_a_to_a   : AXIOM Integral(a,a,f) = 0
   
     Integrable?_inside : AXIOM a <= x AND x <= y AND y <= b AND
         Integrable?(a,b,f) IMPLIES Integrable?(x,y,f)


     Integral_const_fun: AXIOM Integrable?(a, b, const_fun[T](D)) AND
                               Integral(a,b,const_fun(D)) = D*(b-a)


     Integral_const_restrict: AXIOM 
                 (FORALL (x: Closed_interval(a,b)): f(x) = D) IMPLIES
                                    Integrable?(a,b,f) AND
                                    Integral(a,b,f) = D*(b-a)


     Integral_rev: AXIOM Integrable?(a, b, f) IMPLIES
                         Integrable?(b, a, f) AND
                         Integral(b, a, f) = - Integral(a, b, f)


     continuous_Integrable?: AXIOM 
                              (FORALL (x: Closed_interval(a,b)):
                                         continuous?(f,x))
                            IMPLIES Integrable?(a,b,f)


     cont_Integrable?: LEMMA continuous?(f) IMPLIES Integrable?(a,b,f)

     cont_fun_Integrable?: COROLLARY continuous?(f)
                                      IMPLIES Integrable?(a,b,f)


  %  -------------- Linearity Properties of Integral ---------------------

     Integral_scal: AXIOM Integrable?(a,b,f) IMPLIES
                              Integrable?(a,b,D*f) AND
                  Integral(a,b,D*f) = D*Integral(a,b,f)

     Integral_sum: AXIOM Integrable?(a,b,f) AND Integrable?(a,b,g) IMPLIES
                                 Integrable?(a,b,(LAMBDA x: f(x) + g(x)))
                            AND
                Integral(a,b,(LAMBDA x: f(x) + g(x))) =
                   Integral(a,b,f) + Integral(a,b,g)


     Integral_diff: LEMMA Integrable?(a,b,f) AND Integrable?(a,b,g) IMPLIES
                                 Integrable?(a,b,(LAMBDA x: f(x) - g(x)))
                            AND
                Integral(a,b,(LAMBDA x: f(x) - g(x))) =
                   Integral(a,b,f) - Integral(a,b,g)

     Integral_split: AXIOM Integrable?(a,b,f) AND Integrable?(b,c,f) 
                               IMPLIES Integrable?(a,c,f) AND
                             Integral(a,b,f) + Integral(b,c,f) = Integral(a,c,f) 

     Integral_chg_one_pt: AXIOM FORALL (y: Closed_interval(a,b)):
                                Integrable?(a,b,f) 
                      IMPLIES Integrable?(a,b,f WITH [(y) := yv]) AND
                         Integral(a,b,f WITH [(y) := yv]) = Integral(a,b,f) 

  %  ---------------- Boundedness of Integral -----------------------------


     Integral_ge_0: AXIOM a < b AND Integrable?(a,b,f) AND 
                      (FORALL (x: Closed_interval(a,b)): f(x) >= 0) IMPLIES
                             Integral(a,b,f) >= 0


     Integral_ge_0_open: AXIOM a <= b AND Integrable?(a,b,f) AND 
                      (FORALL (x: Open_interval(a,b)): f(x) >= 0) IMPLIES
                             Integral(a,b,f) >= 0


     Integral_bound: AXIOM a < b AND Integrable?(a,b,f) AND 
                             (FORALL (x: Closed_interval(a,b)): 
                                      m <= f(x) AND f(x) <= M )
             IMPLIES m*(b-a) <= Integral(a,b,f) AND Integral(a,b,f) <= M*(b-a)


     Integral_bounded: AXIOM Integrable?(a,b,f) AND
                 (FORALL (x: Closed_interval(a,b)): abs(f(x)) <= M) IMPLIES
                    abs(Integral(a,b,f)) <= M*abs(b-a)


     Integral_le : AXIOM a < b AND Integrable?(a,b,f) AND Integrable?(a,b,g)
                         AND (FORALL (x: closed_interval(a,b)): f(x) <= g(x)) 
                      IMPLIES 
                         Integral(a,b,f) <= Integral(a,b,g) 

  %   bounded_on?(a,b,f): bool = (EXISTS (B: real): 
  %                   (FORALL (x: closed_interval(a,b)): abs(f(x)) <= B))


     % Integrable_bounded: LEMMA Integrable?(a,b,f) 
     %                        IMPLIES 
     %                             LET l = real_defs.min(a,b), 
     %                                 u = real_defs.max(a,b) IN
     %                           bounded_on?(l, u, f)


     Integral_neg: LEMMA Integrable?(a,b,f) IMPLIES 
                              Integrable?(a,b,-f) AND
                              Integral(a,b,-f) = -Integral(a,b,f)

     Integral_restr_eq: AXIOM (FORALL (x: Open_interval(a,b)): f(x) = g(x))
                              AND Integrable?(a,b,f)
                            IMPLIES Integrable?(a,b,g) AND
                                     Integral(a,b,g) = Integral(a,b,f)

  END integral

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 24, column 13) for  integral_def[T]
      % generated from assumption integral_def.connected_domain
  IMP_integral_def_TCC1: OBLIGATION connected?[T];

  % Assuming TCC generated (at line 24, column 13) for  integral_def[T]
      % generated from assumption integral_def.not_one_element
  IMP_integral_def_TCC2: OBLIGATION not_one_element?[T];

  % Subtype TCC generated (at line 47, column 42) for  f
      % expected type  Integrable_funs[T](a, a)
  Integral_a_to_a_TCC1: OBLIGATION
    FORALL (a: T, f: [T -> real]): Integrable?[T](a, a, f);


body:
  fundamental_theorem[T: TYPE+ FROM real]: THEORY
  %------------------------------------------------------------------------------
  %
  %  Theory and proofs taken from Introduction to Analysis (Maxwell Rosenlight)
  %
  %  Author:  Rick Butler               NASA Langley
  %
  %  Note: some material moved to theory indefinite_integral on 7/20/07
  %
  %------------------------------------------------------------------------------

  BEGIN

     ASSUMING
        IMPORTING deriv_domain_def[T]

        connected_domain : ASSUMPTION connected?[T]

        not_one_element : ASSUMPTION not_one_element?[T]

     ENDASSUMING

     IMPORTING deriv_domain_def

     deriv_domain: LEMMA deriv_domain?[T]
     IMPORTING integral, derivative_props[T]

     a,b,c,x: VAR T
     f,F,G: VAR [T -> real]

  %  NOTE: LEMMA "continuous_Integrable?[T]" implicitly used throughout

     fundamental: AXIOM continuous?(f) AND
                          (FORALL x: F(x) = Integral(a,x,f)) 
                     IMPLIES derivable?(F) AND deriv(F) = f

     fundamental2: THEOREM continuous?(f) 
                                IMPLIES (EXISTS F: derivable?(F) AND deriv(F) = f)

     fundamental3: AXIOM derivable?(F) AND deriv(F) = f AND continuous?(f) 
                              IMPLIES Integrable?(a,b,f) AND
                                      Integral(a,b,f) = F(b) - F(a)
                                        
     derivable_Integrable?: COROLLARY derivable?(f)
                                      IMPLIES Integrable?(a,b,f)

     fundamental3b: COROLLARY derivable?(F) AND continuous?(deriv(F))
                              IMPLIES Integrable?(a,b,deriv(F)) AND
                                      Integral(a,b,deriv(F)) = F(b) - F(a)

  END fundamental_theorem

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 26, column 23) for  derivative_props[T]
      % generated from assumption derivative_props.connected_domain
  IMP_derivative_props_TCC1: OBLIGATION connected?[T];

  % Assuming TCC generated (at line 26, column 23) for  derivative_props[T]
      % generated from assumption derivative_props.not_one_element
  IMP_derivative_props_TCC2: OBLIGATION not_one_element?[T];

  % Subtype TCC generated (at line 34, column 55) for  f
      % expected type  Integrable_funs[T](a, x)
  fundamental_TCC1: OBLIGATION
    FORALL (a: T, f: [T -> real]):
      continuous?(f) IMPLIES (FORALL (x): Integrable?[T](a, x, f));

  % Assuming TCC generated (at line 25, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  fundamental_TCC2: OBLIGATION
    FORALL (F: [T -> real], a: T, f: [T -> real]):
      (FORALL x: F(x) = Integral(a, x, f)) AND continuous?(f) IMPLIES
       deriv_domain?[T];

  % Assuming TCC generated (at line 25, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  fundamental2_TCC1: OBLIGATION
    FORALL (f: [T -> real]): continuous?(f) IMPLIES deriv_domain?[T];

  % Assuming TCC generated (at line 25, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  fundamental3_TCC1: OBLIGATION deriv_domain?[T];


body:
  indefinite_integral[T: TYPE+ FROM real]: THEORY
  %------------------------------------------------------------------------------
  %
  %  Author:  Rick Butler               NASA Langley
  %
  %  convention:
  %       Definite integral  :  Integral(a,b,f)
  %       Indefinite integral:  integral(f)
  %
  %------------------------------------------------------------------------------

  BEGIN

     ASSUMING
        IMPORTING deriv_domain_def[T]

        connected_domain : ASSUMPTION connected?[T]


        not_one_element : ASSUMPTION not_one_element?[T]

     ENDASSUMING

     deriv_domain: LEMMA deriv_domain?[T]
     IMPORTING integral[T], derivative_props[T]

     a,b,c,x: VAR T
     f,g,F,G,H: VAR [T -> real]

     antiderivative?(F,f): bool = derivable?(F) AND deriv(F) = f


     antiderivative_lem: LEMMA antiderivative?(F,f) AND derivable?(G) AND
                               deriv(G) = f
                               IMPLIES (EXISTS (c: real): F = G + const_fun(c))

     derivs_eq:     THEOREM derivable?(F) AND derivable?(G) AND deriv(F) = deriv(G)
                           IMPLIES (EXISTS (c: real): F = G + const_fun(c))


     % ------ indefinite integral defined over continuous functions ------

     integrable?(f): bool = (EXISTS F: antiderivative?(F,f))

     integrable_fun: TYPE = { f | integrable?(f)}

     IMPORTING fundamental_theorem[T]


     cont_fun_integrable?: LEMMA continuous?(f) IMPLIES integrable?(f)


     integral(f: integrable_fun): { F: [T -> real] | 
                                         derivable?(F) AND deriv(F) = f }


     integral_lem: LEMMA integrable?(f) AND integral(f) = F AND 
                         derivable?(G) AND deriv(G) = f
                               IMPLIES (EXISTS (c: real): F = G + const_fun(c))


     deriv_integ: LEMMA derivable?(F) IMPLIES integrable?[T](deriv(F))



     indef_integral_thm : THEOREM derivable?(F) IMPLIES
                                  (EXISTS (c: real): 
                                      integral(deriv(F)) = F + const_fun(c))


     fundamental_indef  : THEOREM continuous?(f) IMPLIES 
                                    Integrable?(a,b,f) AND
                                    Integral(a,b,f) = integral(f)(b) - integral(f)(a)




  END indefinite_integral

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 25, column 13) for  integral[T]
      % generated from assumption integral.connected_domain
  IMP_integral_TCC1: OBLIGATION connected?[T];

  % Assuming TCC generated (at line 25, column 13) for  integral[T]
      % generated from assumption integral.not_one_element
  IMP_integral_TCC2: OBLIGATION not_one_element?[T];

  % Assuming TCC generated (at line 25, column 13) for  derivatives[T]
      % generated from assumption derivatives.deriv_domain
  antiderivative?_TCC1: OBLIGATION deriv_domain?[T];

  % Existence TCC generated (at line 53, column 3) for
      % integral(f: integrable_fun):
      %       {F: [T -> real] | derivable?(F) AND deriv(F) = f}
  integral_TCC1: OBLIGATION
    EXISTS (x:
              [f: integrable_fun ->
                 {F: [T -> real] | derivable?[T](F) AND deriv[T](F) = f}]):
      TRUE;

  % Subtype TCC generated (at line 68, column 45) for  deriv(F)
      % expected type  f: integrable_fun
  indef_integral_thm_TCC1: OBLIGATION
    FORALL (F: [T -> real]): derivable?(F) IMPLIES integrable?(deriv[T](F));

  % Subtype TCC generated (at line 73, column 61) for  f
      % expected type  f: integrable_fun
  fundamental_indef_TCC1: OBLIGATION
    FORALL (a, b: T, f: [T -> real]):
      continuous?(f) AND Integrable?(a, b, f) IMPLIES integrable?(f);


body:
  table_of_integrals[T: TYPE+ FROM real]: THEORY
  %------------------------------------------------------------------------------
  %
  %  New experimental:  Theorems will be added as they are needed
  %
  %  Author:  Rick Butler               NASA Langley
  %------------------------------------------------------------------------------

  BEGIN

     ASSUMING
        IMPORTING deriv_domain_def[T]

        connected_domain : ASSUMPTION connected?[T]

        not_one_element : ASSUMPTION not_one_element?[T]

     ENDASSUMING

     IMPORTING fundamental_theorem[T], indefinite_integral[T]

     a,b,x: VAR T

  %  ------ Integral c x^n  = (c/(n+1))*x^(n+1) -----

     antideriv_x_to_n: LEMMA FORALL (n: posnat, c: real):
                              LET f = (LAMBDA x: c*x^n),
                                  F = (LAMBDA x: (c/(n+1))*x^(n+1)) IN
                              antiderivative?(F,f)


     integral_x_to_n: LEMMA FORALL (n: posnat, c: real):
                              LET f = (LAMBDA x: c*x^n) IN
                              Integrable?(a,b,f) AND 
                           LET F = (LAMBDA x: (c/(n+1))*x^(n+1)) IN
                       Integral(a,b,f) = F(b) - F(a)

     integral_linear: LEMMA FORALL (mm: real, bb: real):
                              LET f = (LAMBDA x: mm*x+bb) IN
                              Integrable?(a,b,f) AND 
                           LET F = (LAMBDA x: (mm/2)*x^2 +bb*x) IN
                       Integral(a,b,f) = F(b) - F(a)

     integral_quadratic: LEMMA FORALL (A,B,C: real):
                         Integrable?(a,b, LAMBDA x: A*x^2+B*x+C) AND 
                         LET F =(LAMBDA x: (A/3)*x^3 +(B/2)*x^2 +C*x) IN
                         Integral(a,b, LAMBDA x: A*x^2+B*x+C) = F(b)-F(a)

   
  %  -------

  %   IMPORTING sqrt_derivative

  %   integral_a_to_x: LEMMA LET f = (LAMBDA x: a^^x) IN
  %                              Integrable?(a,b,f) AND 
  %                              Integral(a,b,f) = F(b) - F(a)

  %   integral_1_div_sqrt: LEMMA LET f = (LAMBDA (t: nnreal): 1/sqrt(t)) IN
  %                           a > 0 AND b > 0 IMPLIES  
  %                         Integrable?(a,b,f) AND
  %                         Integral(a, b, f)  = 2*sqrt(b) - 2*sqrt(a)



  END table_of_integrals

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 20, column 13) for  fundamental_theorem[T]
      % generated from assumption fundamental_theorem.connected_domain
  IMP_fundamental_theorem_TCC1: OBLIGATION connected?[T];

  % Assuming TCC generated (at line 20, column 13) for  fundamental_theorem[T]
      % generated from assumption fundamental_theorem.not_one_element
  IMP_fundamental_theorem_TCC2: OBLIGATION not_one_element?[T];

  % Subtype TCC generated (at line 27, column 51) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  antideriv_x_to_n_TCC1: OBLIGATION FORALL (n: posnat, x): x /= 0 OR n >= 0;

  % Subtype TCC generated (at line 28, column 60) for  (n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  antideriv_x_to_n_TCC2: OBLIGATION
    FORALL (n: posnat, c: real, f: [T -> real]):
      f = (LAMBDA x: c * x ^ n) IMPLIES
       (FORALL (x1): x1 /= 0 OR (n + 1) >= 0);

  % Subtype TCC generated (at line 41, column 53) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  integral_linear_TCC1: OBLIGATION
    FORALL (a, b: T, mm: real, bb: real, f: [T -> real]):
      Integrable?(a, b, f) AND f = (LAMBDA x: mm * x + bb) IMPLIES
       (FORALL (x1): x1 /= 0 OR 2 >= 0);

  % Subtype TCC generated (at line 45, column 54) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  integral_quadratic_TCC1: OBLIGATION FORALL (x): x /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 46, column 49) for  3
      % expected type  {i: int | x /= 0 OR i >= 0}
  integral_quadratic_TCC2: OBLIGATION
    FORALL (a, b: T, A, B, C: real):
      Integrable?(a, b, LAMBDA x: A * x ^ 2 + B * x + C) IMPLIES
       (FORALL (x1): x1 /= 0 OR 3 >= 0);

  % Subtype TCC generated (at line 46, column 60) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  integral_quadratic_TCC3: OBLIGATION
    FORALL (a, b: T, A, B, C: real):
      Integrable?(a, b, LAMBDA x: A * x ^ 2 + B * x + C) IMPLIES
       (FORALL (x1): x1 /= 0 OR 2 >= 0);


body:
  top: THEORY
  %------------------------------------------------------------------------
  %
  % An Axiomatic Theory of Trigonometry (Demonstrated to be sound in trig_fnd
  %                                      library)
  %
  %       by Cesar Munoz                     Langley ICASE Institute
  %          Victor Carreno                  NASA Langley
  %          Ricky Butler                    NASA Langley
  %          Gilles Dowek                    INRIA, Domaine de Voluceau
  %          Alfons Geser                    Langley ICASE Institute
  %          Ben Di Vito                     NASA Langley
  % 
  %      Version 1.0    3/27/01
  %      Version 1.1    6/27/01              New lemmas added:
  %                                          -------------------------------- 
  %                                          tan_period, sin_k_pi , cos_2k_pi,  
  %                                          cos_k_pi  , sin_k_pi2, tan_k_pi,
  %                                          sin_eq_1  , cos_eq_1 , sin_eq_sin,
  %                                          cos_eq_cos, tan_eq_tan, sin_eq_pm1,
  %                                          cos_eq_pm1, and prelude_aux lemmas
  %
  %      Version 1.2    6/28/01              Theory "trig_rew" added
  %
  %      Version 1.3    10/27/03             Corrected, foundational theory
  %                                          (David Lester)
  %
  %      Version 1.31   11/29/03             Renamed PI to pi (Cesar A. Munoz)
  %
  %      Version 1.32   2/6/04               Theory "tan_approx" added (C. Munoz)
  %
  %      Version 1.33   5/23/04              atan2 added (D Lester)
  %
  %      Version 1.34   5/30/04              atan/asin/acos added (D Lester)
  %
  %      Version 1.4    4/15/05              approx made consistent with trig_fnd
  %
  % INDEX:
  % ------
  %
  %
  %     trig_basic:
  %     -----------
  %         - definition of pi with crude upper and lower bounds
  %         - definition of sin, cos, and tan
  %         - pythagorean properties: sq(sin(a)) + sq(cos(a)) = 1 
  %         - sum and difference of two angles
  %         - double angle formulas
  %         - negative properties, e.g. sin(-a)
  %         - periodicity, e.g. sin(a) = sin(a + 2 * j * pi) 
  %         - co-function identities, e.g. sin(pi/2 - a) = cos(a)
  %         - location of zeros of trig functions
  %
  %      trig_values                            Lemma names
  %      -----------                   ------------------------------------
  %         - trig functions at 0      : sin_0     , cos_0     , tan_0 
  %         - trig functions at pi/6   : sin_pi6   , cos_pi6   , tan_pi6 
  %         - trig functions at pi/4   : sin_pi4   , cos_pi4   , tan_pi4 
  %         - trig functions at pi/3   : sin_pi3   , cos_pi3   , tan_pi3 
  %         - trig functions at pi/2   : sin_pi2   , cos_pi2   , tan_pi2 
  %         - trig functions at pi     : sin_pi    , cos_pi    , tan_pi 
  %         - trig functions at 2*pi/3 : sin_2pi3  , cos_2pi3  , tan_2pi3 
  %         - trig functions at 3*pi/4 : sin_3pi4  , cos_3pi4  , tan_3pi4 
  %         - trig functions at 5*pi/4 : sin_5pi4  , cos_5pi4  , tan_5pi4 
  %
  %      trig_ineq
  %      ---------
  %         - regions where functions are greater than 0
   %         - regions where functions are less    than 0
  %         - regions where functions are increasing
  %         - regions where functions are decreasing
  %
  %      trig_extra
  %      ----------
  %         - reduction theorems
  %         - sum and product identities
  %         - half-angle identities and zeros
  %         - triple angle formulas
  %
  %      trig_approx
  %      -----------
  %          - taylor series approximations to trig functions:
  %               sin_approx(a,n): sum first n terms of taylor expansion of sin
  %               cos_approx(a,n): sum first n terms of taylor expansion of cos
  %      
  %      tan_approx
  %      ----------
  %          - taylor series approximations for tangent
  %
  %      law_cosines
  %      -----------
  %         - the law of cosines in a coordinate geometry formulation
  %
  %      trig_degree
  %      -----------
  %         - trig functions that take arguments in degrees: sind, cosd
  %         - defines conversions toRad, toDeg
  %
  %      trig_inv
  %      -------------
  %         - provides interface to atan, asin, acos, atan2
  %
  %      -------------
  %         - defines inverse trig functions: arcsin, arccos, and arctan 
  %
  %      trig_rew
  %      -------------
  %         - Experimental auto-rewrite-theory background library
  %
  %
  %------------------------------------------------------------------------

  BEGIN
     IMPORTING trig_doc,      % Some more documentation (Rationale)

               trig,          % typical needs
               trig_full,     % everything

  % --------------------- The above import the following ------------------

               trig_basic,    % basic properties 
               trig_values,   % values of functions for special arguments
               trig_ineq,     % trig inequalities
               trig_extra,    % sum and product, half-angle, reductions and zeros
               trig_approx,   % taylor series approximations to trig functions:
               tan_approx,    % approximatan2_propsations fprior tangent
               law_cosines,   % law of cosines
               trig_degree,   % conversions to degrees
               trig_inverses, % interface to atan, asin, acos, atan2
               trig_rew,      % auto-rewrites
               asin,          % asin properties
               acos,          % acos properties
               atan,          % atan properties
               atan_values,   % atan for specific values
               atan2,         % two-argument arc tangent
               atan2_props,   % additional properties of atan2 and values
               jatan2,        % Java atan2

               to2pi,         % normalization of radians to 2pi

               sincos,        % continuity, derivablility of sin, cos
               deriv_sincos,
               integral_sincos,
               integral_indef_sincos

  END top


body:
  trig_basic : THEORY
  %-----------------------------------------------------------------------------
  %     trig_basic:
  %     -----------
  %         - definition of pi with crude upper and lower bounds
  %         - definition of sin, cos, and tan
  %         - pythagorean properties: sq(sin(a)) + sq(cos(a)) = 1 
  %         - sum and difference of two angles
  %         - double angle formulas
  %         - negative properties, e.g. sin(-a)
  %         - periodicity, e.g. sin(a) = sin(a + 2 * j * pi) 
  %         - co-function identities, e.g. sin(pi/2 - a) = cos(a)
  %         - location of zeros of trig functions
  %
  %   Version 1.1 27/10/03 Axiomatic Version 
  %                        edited from trig_basic in the "trig_fnd" librart

  %   GOAL:  To reduce the amount of stuff that has to be imported
  %-----------------------------------------------------------------------------
  BEGIN

    IMPORTING reals@sqrt %, sincos_phase

    a,b,c,d           : VAR real
    nnc               : VAR nonneg_real 
    j                 : VAR integer

    
  %  pi_lb  : real = 314/100
  %  pi_ub  : real = 315/100

    pi_lb : posreal = 31415926/10000000
    pi_ub : posreal = 31415927/10000000

    pi     : {r:posreal | r > pi_lb AND r < pi_ub}   %% ADDED %%

  % pi_bound : JUDGEMENT pi HAS_TYPE {r:posreal | pi_lb <= r AND r <= pi_ub}

  % -------------------- definition of sin and cos --------------------

    trig_range  : TYPE = {a | -1 <= a AND a <= 1}
    trig_phase  : TYPE+ = {x:nnreal| x < 2*pi} CONTAINING 0


    sin(x:real) : real % = sin_phase(x-2*pi*floor(x/(2*pi)))
    cos(x:real) : real % = cos_phase(x-2*pi*floor(x/(2*pi)))

    sin_range_ax: AXIOM -1 <= sin(a) AND sin(a) <= 1
    cos_range_ax: AXIOM -1 <= cos(a) AND cos(a) <= 1

    sin_range   : JUDGEMENT sin(a) HAS_TYPE trig_range
    cos_range   : JUDGEMENT cos(a) HAS_TYPE trig_range

    Tan?(a)        : bool = cos(a) /= 0
   
    tan(a:(Tan?))  : real = sin(a)/cos(a)

  % -------------------- Pythagorean Property --------------------
   
    sin2_cos2    : AXIOM sq(sin(a)) + sq(cos(a)) = 1

    cos2         : LEMMA sq(cos(a)) = 1 - sq(sin(a)) 

    sin2         : LEMMA sq(sin(a)) = 1 - sq(cos(a)) 

  % --------------------- Basic Values ----------------------------

    cos_0         : AXIOM cos(0) = 1 

    sin_0         : LEMMA sin(0) = 0

    sin_pi2       : AXIOM sin(pi/2) = 1

    cos_pi2       : LEMMA cos(pi/2) = 0

    tan_0         : LEMMA tan(0) = 0

  % --------------------- Negative Properties ----------------------

    sin_neg : AXIOM sin(-a) = -sin(a) 
    cos_neg : AXIOM cos(-a) = cos(a) 
    tan_neg : LEMMA FORALL(a:(Tan?)): tan(-a) = -tan(a)


  % -------------------- Co-Function Identities -----------------------

    cos_sin    : AXIOM cos(a) = sin(a+pi/2)
    sin_cos    : LEMMA sin(a) = -cos(a+pi/2)
    sin_shift  : LEMMA sin(pi/2 - a) = cos(a)
    cos_shift  : LEMMA cos(pi/2 - a) = sin(a)

  % --------------------- Arguments involving pi ---------------------

    neg_cos     : LEMMA -cos(a) = cos(a+pi)
    neg_sin     : LEMMA -sin(a) = sin(a+pi)

    sin_pi      : AXIOM sin(pi) = 0
    cos_pi      : AXIOM cos(pi) = -1
    tan_pi      : LEMMA tan(pi) = 0
    sin_3pi2    : LEMMA sin(3*pi/2) = -1
    cos_3pi2    : LEMMA cos(3*pi/2) = 0
    sin_2pi     : AXIOM sin(2*pi) = 0
    cos_2pi     : AXIOM cos(2*pi) = 1
    tan_2pi     : LEMMA tan(2*pi) = 0

  % ----------------- Sum and Difference of Two Angles ----------------

    sin_plus  : AXIOM sin(a + b) = sin(a)*cos(b) + cos(a)*sin(b)   
    sin_minus : LEMMA sin(a - b) = sin(a)*cos(b) - sin(b)*cos(a)

    cos_plus  : LEMMA cos(a + b) = cos(a)*cos(b) - sin(a)*sin(b)
    cos_minus : LEMMA cos(a - b) = cos(a)*cos(b) + sin(a)*sin(b)

    sin_pi_minus: LEMMA sin(pi - a) = sin(a)
    cos_pi_minus: LEMMA cos(pi - a) = -cos(a)

    tan_plus  : LEMMA Tan?(a) AND Tan?(b) AND Tan?(a+b) AND
                      tan(a) * tan(b) /= 1 IMPLIES                 
                        tan(a + b) = (tan(a) + tan(b))/(1 - tan(a)*tan(b)) 

    tan_minus : LEMMA Tan?(a) AND Tan?(b) AND Tan?(a-b) AND
                      tan(a) * tan(b) /= -1 IMPLIES                 
                        tan(a - b) = (tan(a) - tan(b))/(1 + tan(a)*tan(b))

    arc_sin_cos  : AXIOM sq(a)+sq(b)=sq(c) IMPLIES
                              EXISTS d: a = c*cos(d) AND b = c*sin(d)

    pythagorean  : LEMMA sq(a)+sq(b)=sq(nnc) IMPLIES
                              EXISTS(alpha:real): nnc=a*cos(alpha)+b*sin(alpha)

  % -------------------- Double Angle Formulas -------------------- 

     sin_2a     : LEMMA sin(2*a) = 2 * sin(a) * cos(a)
     cos_2a     : LEMMA cos(2*a) = cos(a)*cos(a) - sin(a)*sin(a)
     cos_2a_cos : LEMMA cos(2*a) = 2 * cos(a)*cos(a) - 1
     cos_2a_sin : LEMMA cos(2*a) = 1 - 2 * sin(a)*sin(a)
     tan_2a     : LEMMA Tan?(a) AND Tan?(2*a) AND 
                        tan(a) * tan(a) /= 1 IMPLIES 
                          tan(2*a) = 2 * tan(a)/(1 - tan(a) * tan(a))
   
  % ------------------------- Periodicity -----------------------------

  %  IMPORTING reals@prelude_aux_reals 

    n: VAR nat
    k: VAR integer

    sin_period  : LEMMA sin(a) = sin(a + 2 * j * pi) 
    cos_period  : LEMMA cos(a) = cos(a + 2 * j * pi) 
    tan_period  : LEMMA Tan?(a) IMPLIES tan(a) = tan(a + j * pi) 

    sin_k_pi    : LEMMA sin(k*pi) = 0
    cos_2k_pi   : LEMMA cos(2*k*pi) = 1
    cos_k_pi    : LEMMA cos(k*pi) = (-1)^(k)
    sin_k_pi2   : LEMMA sin(k*pi + pi/2) = (-1)^k 
    tan_k_pi    : LEMMA tan(k*pi) = 0

  % -------------------- Characterization of zeroes -------------------


    sin_eq_0     : AXIOM sin(a) = 0 IFF EXISTS (i: int): a = i * pi

    cos_eq_0     : LEMMA cos(a) = 0 IFF EXISTS (i: int): a = i * pi + pi/2

    sin_eq_0_2pi : COROLLARY 0 <= a AND a <= 2*pi IMPLIES
                      (sin(a)=0 IFF a=0 OR a=pi OR a=2*pi)

    cos_eq_0_2pi : COROLLARY 0 <= a AND a <= 2*pi IMPLIES
                      (cos(a)=0 IFF a=pi/2 OR a=3*pi/2)

    tan_eq_0     : LEMMA FORALL (a: (Tan?)):
                      (tan(a) = 0 IFF EXISTS (i: int): a = i * pi)


  % ---------------------- Maximum Points -----------------------------
   
    sin_eq_1     : LEMMA sin(a) = 1 IFF EXISTS (i: int): a = 2 * i * pi + pi/2
    cos_eq_1     : LEMMA cos(a) = 1 IFF EXISTS (i: int): a = 2 * i * pi 

  END trig_basic

addendum:
  %%% ================ Addendum: generated declarations ================

  % Existence TCC generated (at line 35, column 2) for
      % pi: {r: posreal | r > pi_lb AND r < pi_ub}
  pi_TCC1: OBLIGATION
    EXISTS (x: {r: posreal | r > pi_lb AND r < pi_ub}): TRUE;

  % Subtype TCC generated (at line 42, column 56) for  0
      % expected type  trig_phase
  trig_phase_TCC1: OBLIGATION 0 < 2 * pi;

  % Judgement subtype TCC generated (at line 51, column 26) for  sin(a)
      % expected type  trig_range
  sin_range: OBLIGATION FORALL (a): -1 <= sin(a) AND sin(a) <= 1;

  % Judgement subtype TCC generated (at line 52, column 26) for  cos(a)
      % expected type  trig_range
  cos_range: OBLIGATION FORALL (a): -1 <= cos(a) AND cos(a) <= 1;

  % Subtype TCC generated (at line 56, column 33) for  cos(a)
      % expected type  nznum
  tan_TCC1: OBLIGATION FORALL (a: (Tan?)): cos(a) /= 0;

  % Subtype TCC generated (at line 76, column 28) for  0
      % expected type  (Tan?)
  tan_0_TCC1: OBLIGATION Tan?(0);

  % Subtype TCC generated (at line 82, column 40) for  -a
      % expected type  (Tan?)
  tan_neg_TCC1: OBLIGATION FORALL (a: (Tan?)): Tan?(-a);

  % Subtype TCC generated (at line 99, column 26) for  pi
      % expected type  (Tan?)
  tan_pi_TCC1: OBLIGATION Tan?(pi);

  % Subtype TCC generated (at line 104, column 26) for  2 * pi
      % expected type  (Tan?)
  tan_2pi_TCC1: OBLIGATION Tan?(2 * pi);

  % Subtype TCC generated (at line 119, column 54) for  (1 - tan(a) * tan(b))
      % expected type  nznum
  tan_plus_TCC1: OBLIGATION
    FORALL (a, b: real):
      tan(a) * tan(b) /= 1 AND Tan?(a + b) AND Tan?(b) AND Tan?(a) IMPLIES
       (1 - tan(a) * tan(b)) /= 0;

  % Subtype TCC generated (at line 123, column 54) for  (1 + tan(a) * tan(b))
      % expected type  nznum
  tan_minus_TCC1: OBLIGATION
    FORALL (a, b: real):
      tan(a) * tan(b) /= -1 AND Tan?(a - b) AND Tan?(b) AND Tan?(a) IMPLIES
       (1 + tan(a) * tan(b)) /= 0;

  % Subtype TCC generated (at line 139, column 47) for  (1 - tan(a) * tan(a))
      % expected type  nznum
  tan_2a_TCC1: OBLIGATION
    FORALL (a: real):
      tan(a) * tan(a) /= 1 AND Tan?(2 * a) AND Tan?(a) IMPLIES
       (1 - tan(a) * tan(a)) /= 0;

  % Subtype TCC generated (at line 150, column 51) for  a + j * pi
      % expected type  (Tan?)
  tan_period_TCC1: OBLIGATION
    FORALL (a: real, j: integer): Tan?(a) IMPLIES Tan?(a + j * pi);

  % Subtype TCC generated (at line 156, column 26) for  k * pi
      % expected type  (Tan?)
  tan_k_pi_TCC1: OBLIGATION FORALL (k: integer): Tan?(k * pi);


body:
  atan: THEORY
  %------------------------------------------------------------------------------
  %
  %  Axiomatic atan
  %
  %          David Lester                    Manchester University
  % 
  %------------------------------------------------------------------------------
  BEGIN


    IMPORTING reals@sq, reals@sigma, reals@sqrt
    IMPORTING reals@factorial
  %  IMPORTING reals@harmonic_polynomials %,polynomial_deriv
    IMPORTING reals@binomial, reals@real_fun_preds 
  %  IMPORTING reals@polynomials         %%% INCLUDING THIS CAUSES BUG
                                         %%% bin out of date when in complex lib

    posreal_ge1: NONEMPTY_TYPE = {x:real | x >= 1} CONTAINING 1

    x,y:   VAR real
    px,py: VAR posreal
    nx:    VAR negreal
    nnx:   VAR nnreal
    nzx:   VAR nzreal
    n,m:   VAR nat
    pn:    VAR posnat

    IMPORTING trig_basic                %% to get value of pi here

  % --- from sincos_def ---
    a: VAR real  
    tan_value_TCC: AXIOM -pi/2 < a AND a <  pi/2 IMPLIES Tan?(a)

    real_abs_lt_pi2: NONEMPTY_TYPE = {x | -pi/2 < x AND x < pi/2} CONTAINING 0

    atan(x:real):real_abs_lt_pi2 % = atan_value(x)

  % non-A&S definitions

    pi_value: AXIOM pi = 4*atan(1)      %%%%% RWB conflicts with trig_basic

    atan_strict_increasing: AXIOM strict_increasing?(atan)

    atan_bij              : AXIOM bijective?[real,real_abs_lt_pi2](atan)
    atan_0                : AXIOM atan(0) = 0

    atan_inv              : AXIOM atan(1/px) = pi/2-atan(px)
    atan_inv_neg          : AXIOM atan(1/nx) = -pi/2-atan(nx)


  % A&S defs


    acot(nzx:nzreal):nzreal    = atan(1/nzx)                             %  4.4.8

    atan_neg: AXIOM atan(-x)   = -atan(x)                                % 4.4.16
    acot_neg: LEMMA acot(-nzx) = -acot(nzx)                              % 4.4.19

    atan_minus: AXIOM                                                    % 4.4.34
    (-1 < x*y =>         atan(x)-atan(y)    = atan((x-y)/(1+x*y))) AND
    (x*y < -1 & y > 0 => atan(x)-atan(y)+pi = atan((x-y)/(1+x*y))) AND
    (x*y < -1 & y < 0 => atan(x)-atan(y)-pi = atan((x-y)/(1+x*y)))

    atan_plus:  LEMMA                                                    % 4.4.34
    (x*y < 1 => atan(x)+atan(y)            = atan((x+y)/(1-x*y))) AND
    (1 < x*y & y > 0 => atan(x)+atan(y)-pi = atan((x+y)/(1-x*y))) AND
    (1 < x*y & y < 0 => atan(x)+atan(y)+pi = atan((x+y)/(1-x*y)))


    atan_sub_swap : LEMMA
      x /= 0 AND y /= 0 IMPLIES
      atan(x/y)-atan(y/x) = atan((x^2-y^2)/(2*x*y))

  %  continuous_atan: LEMMA continuous[real](atan)

  % more non-A&S definitions

    atan_1:    LEMMA atan(1) = 4*atan(1/5) - atan(1/239)
    atan_bnds: AXIOM px/(1+px*px) < atan(px) AND atan(px) < px
    pi_bnds:   LEMMA 306/100 < pi AND pi < 319/100


  % atan Taylor's Theorem


    atan_series_coef(n:nat):rat = ((-1)^n)/(2*n+1)
    atan_series_term(x:real):[nat->real]
       = (LAMBDA (n:nat): x^(2*n+1) * atan_series_coef(n))
    atan_series_n(x:real,n:nat):real = sigma(0,n,atan_series_term(x))


    atan_series: AXIOM abs(atan(x)-atan_series_n(x,n)) <= abs(x^(2*n+3))/(2*n+3)

  END atan

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 35, column 75) for  0
      % expected type  real_abs_lt_pi2
  real_abs_lt_pi2_TCC1: OBLIGATION -pi / 2 < 0 AND 0 < pi / 2;

  % Subtype TCC generated (at line 55, column 31) for  atan(1 / nzx)
      % expected type  nzreal
  acot_TCC1: OBLIGATION FORALL (nzx: nzreal): atan(1 / nzx) /= 0;

  % Subtype TCC generated (at line 61, column 56) for  (1 + x * y)
      % expected type  nznum
  atan_minus_TCC1: OBLIGATION
    FORALL (x, y: real): -1 < x * y IMPLIES (1 + x * y) /= 0;

  % Subtype TCC generated (at line 62, column 56) for  (1 + x * y)
      % expected type  nznum
  atan_minus_TCC2: OBLIGATION
    FORALL (x, y: real):
      (-1 < x * y => atan(x) - atan(y) = atan((x - y) / (1 + x * y))) AND
       y > 0 AND x * y < -1
       IMPLIES (1 + x * y) /= 0;

  % Subtype TCC generated (at line 63, column 56) for  (1 + x * y)
      % expected type  nznum
  atan_minus_TCC3: OBLIGATION
    FORALL (x, y: real):
      (-1 < x * y => atan(x) - atan(y) = atan((x - y) / (1 + x * y))) AND
       (x * y < -1 & y > 0 =>
         atan(x) - atan(y) + pi = atan((x - y) / (1 + x * y)))
        AND y < 0 AND x * y < -1
       IMPLIES (1 + x * y) /= 0;

  % Subtype TCC generated (at line 66, column 55) for  (1 - x * y)
      % expected type  nznum
  atan_plus_TCC1: OBLIGATION
    FORALL (x, y: real): x * y < 1 IMPLIES (1 - x * y) /= 0;

  % Subtype TCC generated (at line 67, column 55) for  (1 - x * y)
      % expected type  nznum
  atan_plus_TCC2: OBLIGATION
    FORALL (x, y: real):
      (x * y < 1 => atan(x) + atan(y) = atan((x + y) / (1 - x * y))) AND
       y > 0 AND 1 < x * y
       IMPLIES (1 - x * y) /= 0;

  % Subtype TCC generated (at line 68, column 55) for  (1 - x * y)
      % expected type  nznum
  atan_plus_TCC3: OBLIGATION
    FORALL (x, y: real):
      (x * y < 1 => atan(x) + atan(y) = atan((x + y) / (1 - x * y))) AND
       (1 < x * y & y > 0 =>
         atan(x) + atan(y) - pi = atan((x + y) / (1 - x * y)))
        AND y < 0 AND 1 < x * y
       IMPLIES (1 - x * y) /= 0;

  % Subtype TCC generated (at line 73, column 34) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  atan_sub_swap_TCC1: OBLIGATION
    FORALL (x, y: real): y /= 0 AND x /= 0 IMPLIES x /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 73, column 38) for  2
      % expected type  {i: int | y /= 0 OR i >= 0}
  atan_sub_swap_TCC2: OBLIGATION
    FORALL (x, y: real): y /= 0 AND x /= 0 IMPLIES y /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 73, column 42) for  (2 * x * y)
      % expected type  nznum
  atan_sub_swap_TCC3: OBLIGATION
    FORALL (x, y: real): y /= 0 AND x /= 0 IMPLIES (2 * x * y) /= 0;

  % Subtype TCC generated (at line 89, column 27) for  (2 * n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  atan_series_term_TCC1: OBLIGATION
    FORALL (x: real, n: nat): x /= 0 OR (2 * n + 1) >= 0;

  % Subtype TCC generated (at line 90, column 43) for  0
      % expected type  T_low[nat]
  atan_series_n_TCC1: OBLIGATION 0 >= 0 OR (EXISTS (j: nat): j <= 0);

  % Subtype TCC generated (at line 90, column 45) for  n
      % expected type  T_high[nat]
  atan_series_n_TCC2: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Assuming TCC generated (at line 12, column 22) for  reals@sigma[nat]
      % generated from assumption sigma.connected_domain
  atan_series_n_TCC3: OBLIGATION
    (FORALL (x, y: nat), (z: integer): x <= z AND z <= y IMPLIES z >= 0);

  % Subtype TCC generated (at line 93, column 63) for  (2 * n + 3)
      % expected type  {i: int | x /= 0 OR i >= 0}
  atan_series_TCC1: OBLIGATION
    FORALL (n: nat, x: real): x /= 0 OR (2 * n + 3) >= 0;


body:
  asin: THEORY

    BEGIN
   
    IMPORTING reals@sq, reals@sqrt
    IMPORTING atan
  %  IMPORTING analysis@sqrt_derivative, analysis@derivative_props

  %  real_abs_le1:    NONEMPTY_TYPE = {x:real | abs(x) <= 1}    CONTAINING 0
  %  real_abs_lt1:    NONEMPTY_TYPE = {x:real | abs(x) <  1}    CONTAINING 0
  %  real_abs_le_pi2: NONEMPTY_TYPE = {x:real | abs(x) <= pi/2} CONTAINING 0
    real_abs_le1:   NONEMPTY_TYPE =  {x:real | -1 <= x AND x <= 1}    CONTAINING 0
    real_abs_lt1:   NONEMPTY_TYPE =  {x:real | -1 < x  AND x <  1}    CONTAINING 0
    real_abs_le_pi2: NONEMPTY_TYPE = {x:real | -pi/2 <= x AND x <= pi/2} CONTAINING 0

    x,y:     VAR real_abs_le1
    xne:     VAR real_abs_lt1
    nnx,nny: VAR {x:nnreal | x <= 1}
    nx:      VAR {x:real_abs_le1 | x < 0}
    px:      VAR {x:real_abs_le1 | 0 < x}
    nx_gt1:  VAR {x:negreal | -1 < x}
    px_lt1:  VAR {x:posreal | x < 1}

    asin(x:real_abs_le1):real_abs_le_pi2
      = IF x = -1 THEN -pi/2 ELSIF x < 1 THEN atan(x/sqrt(1-x*x)) ELSE pi/2 ENDIF

    asin_neg_restrict:      LEMMA asin(nx) = -pi/2 - atan(sqrt(1-nx*nx)/nx)
    asin_pos_restrict:      LEMMA asin(px) =  pi/2 - atan(sqrt(1-px*px)/px)
    asin_0:                 LEMMA asin(0)  = 0
    asin_sqrt_half:         LEMMA asin(sqrt(1/2)) = pi/4
    asin_1:                 LEMMA asin(1)  = pi/2
    asin_neg:               LEMMA asin(-x) = -asin(x)
    asin_minus1:            LEMMA asin(-1) = -pi/2
    asin_minus_sqrt_half:   LEMMA asin(-sqrt(1/2)) = -pi/4
    asin_strict_increasing: LEMMA strict_increasing?(asin)
    asin_bij:               LEMMA bijective?[real_abs_le1,real_abs_le_pi2](asin)

    asin_diff: LEMMA                                                     % 4.4.32
        asin(nnx)-asin(nny) = asin(nnx*(sqrt(1-sq(nny)))-nny*(sqrt(1-sq(nnx))))

  %   asin_derivable:  LEMMA
  %                 derivable[real_abs_lt1]((LAMBDA (x:real_abs_lt1):asin(x)),xne)
  %   asin_derivable2: LEMMA
  %                 derivable[real_abs_lt1](LAMBDA (x:real_abs_lt1): asin(x))
  %   deriv_asin_fun:  LEMMA deriv[real_abs_lt1](LAMBDA (x:real_abs_lt1): asin(x))
  %                            = (LAMBDA (x:real_abs_lt1): 1/sqrt(1-sq(x)))

    asin_pos_bnds: AXIOM px < asin(px) AND
               (px*(1-px*px/6) > 0 => asin(px*(1-px*px/6)) < px)

    END asin

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 14, column 82) for  0
      % expected type  real_abs_le_pi2
  real_abs_le_pi2_TCC1: OBLIGATION -pi / 2 <= 0 AND 0 <= pi / 2;

  % Subtype TCC generated (at line 25, column 21) for  -pi / 2
      % expected type  real_abs_le_pi2
  asin_TCC1: OBLIGATION
    FORALL (x: real_abs_le1):
      x = -1 IMPLIES -pi / 2 <= -pi / 2 AND -pi / 2 <= pi / 2;

  % Subtype TCC generated (at line 25, column 56) for  1 - x * x
      % expected type  nnx: nonneg_real
  asin_TCC2: OBLIGATION
    FORALL (x: real_abs_le1): x < 1 AND NOT x = -1 IMPLIES 1 - x * x >= 0;

  % Subtype TCC generated (at line 25, column 51) for  sqrt(1 - x * x)
      % expected type  nznum
  asin_TCC3: OBLIGATION
    FORALL (x: real_abs_le1):
      x < 1 AND NOT x = -1 IMPLIES sqrt(1 - x * x) /= 0;

  % Subtype TCC generated (at line 25, column 44) for
      % atan(x / sqrt(1 - x * x))
      % expected type  real_abs_le_pi2
  asin_TCC4: OBLIGATION
    FORALL (x: real_abs_le1):
      x < 1 AND NOT x = -1 IMPLIES
       -pi / 2 <= atan(x / sqrt(1 - x * x)) AND
        atan(x / sqrt(1 - x * x)) <= pi / 2;

  % Subtype TCC generated (at line 25, column 69) for  pi / 2
      % expected type  real_abs_le_pi2
  asin_TCC5: OBLIGATION
    FORALL (x: real_abs_le1):
      NOT x < 1 AND NOT x = -1 IMPLIES -pi / 2 <= pi / 2 AND pi / 2 <= pi / 2;

  % Subtype TCC generated (at line 27, column 61) for  1 - nx * nx
      % expected type  nnx: nonneg_real
  asin_neg_restrict_TCC1: OBLIGATION
    FORALL (nx: {x: real_abs_le1 | x < 0}): 1 - nx * nx >= 0;

  % Subtype TCC generated (at line 27, column 70) for  nx
      % expected type  nznum
  asin_neg_restrict_TCC2: OBLIGATION
    FORALL (nx: {x: real_abs_le1 | x < 0}): nx /= 0;

  % Subtype TCC generated (at line 28, column 61) for  1 - px * px
      % expected type  nnx: nonneg_real
  asin_pos_restrict_TCC1: OBLIGATION
    FORALL (px: {x: real_abs_le1 | 0 < x}): 1 - px * px >= 0;

  % Subtype TCC generated (at line 28, column 70) for  px
      % expected type  nznum
  asin_pos_restrict_TCC2: OBLIGATION
    FORALL (px: {x: real_abs_le1 | 0 < x}): px /= 0;

  % Subtype TCC generated (at line 30, column 37) for  sqrt(1 / 2)
      % expected type  real_abs_le1
  asin_sqrt_half_TCC1: OBLIGATION -1 <= sqrt(1 / 2) AND sqrt(1 / 2) <= 1;

  % Subtype TCC generated (at line 32, column 37) for  -x
      % expected type  real_abs_le1
  asin_neg_TCC1: OBLIGATION FORALL (x: real_abs_le1): -1 <= -x AND -x <= 1;

  % Subtype TCC generated (at line 34, column 37) for  -sqrt(1 / 2)
      % expected type  real_abs_le1
  asin_minus_sqrt_half_TCC1: OBLIGATION
    -1 <= -sqrt(1 / 2) AND -sqrt(1 / 2) <= 1;

  % Subtype TCC generated (at line 39, column 11) for  nnx
      % expected type  real_abs_le1
  asin_diff_TCC1: OBLIGATION
    FORALL (nnx: {x: nnreal | x <= 1}): -1 <= nnx AND nnx <= 1;

  % Subtype TCC generated (at line 39, column 43) for  1 - sq(nny)
      % expected type  nnx: nonneg_real
  asin_diff_TCC2: OBLIGATION
    FORALL (nny: {x: nnreal | x <= 1}): 1 - sq(nny) >= 0;

  % Subtype TCC generated (at line 39, column 33) for
      % nnx * (sqrt(1 - sq(nny))) - nny * (sqrt(1 - sq(nnx)))
      % expected type  real_abs_le1
  asin_diff_TCC3: OBLIGATION
    FORALL (nnx, nny: {x: nnreal | x <= 1}):
      -1 <= nnx * (sqrt(1 - sq(nny))) - nny * (sqrt(1 - sq(nnx))) AND
       nnx * (sqrt(1 - sq(nny))) - nny * (sqrt(1 - sq(nnx))) <= 1;

  % Subtype TCC generated (at line 49, column 41) for  px * (1 - px * px / 6)
      % expected type  real_abs_le1
  asin_pos_bnds_TCC1: OBLIGATION
    FORALL (px: {x: real_abs_le1 | 0 < x}):
      px < asin(px) AND px * (1 - px * px / 6) > 0 IMPLIES
       -1 <= px * (1 - px * px / 6) AND px * (1 - px * px / 6) <= 1;


body:
  acos: THEORY

    BEGIN

    IMPORTING asin, reals@abs_lems

    nnreal_le_pi: NONEMPTY_TYPE = {x:nnreal | x <= pi}     CONTAINING 0

    x:       VAR real_abs_le1
    xne:     VAR real_abs_lt1
    nnx,nny: VAR {x:nnreal | x <= 1}

    acos(x:real_abs_le1):nnreal_le_pi = pi/2 - asin(x)
    
    acos_neg:               LEMMA acos(-x) = pi-acos(x)
    acos_0:                 LEMMA acos(0)  = pi/2
    acos_sqrt_half:         LEMMA acos(sqrt(1/2)) = pi/4
    acos_1:                 LEMMA acos(1)  = 0
    acos_minus1:            LEMMA acos(-1) = pi
    acos_minus_sqrt_half:   LEMMA acos(-sqrt(1/2)) = 3*pi/4
    acos_strict_decreasing: LEMMA strict_decreasing?(acos)
    acos_bij:               LEMMA bijective?[real_abs_le1,nnreal_le_pi](acos)

    acos_sum: LEMMA                                                     % 4.4.32
        acos(nnx)+acos(nny) = acos(nnx*nny-(sqrt(1-sq(nny)))*(sqrt(1-sq(nnx))))

  %   acos_derivable:  LEMMA
  %                 derivable[real_abs_lt1]((LAMBDA (x:real_abs_lt1):acos(x)),xne)
  %   acos_derivable2: LEMMA
  %                 derivable[real_abs_lt1](LAMBDA (x:real_abs_lt1): acos(x))
  %   deriv_acos_fun:  LEMMA deriv[real_abs_lt1](LAMBDA (x:real_abs_lt1): acos(x))
  %      = (LAMBDA (x:real_abs_lt1): -deriv(LAMBDA (x: real_abs_lt1): asin(x))(x))


    END acos

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 7, column 68) for  0
      % expected type  nnreal_le_pi
  nnreal_le_pi_TCC1: OBLIGATION 0 <= pi;

  % Subtype TCC generated (at line 13, column 38) for  pi / 2 - asin(x)
      % expected type  nnreal_le_pi
  acos_TCC1: OBLIGATION
    FORALL (x: real_abs_le1):
      pi / 2 - asin(x) >= 0 AND pi / 2 - asin(x) <= pi;

  % Subtype TCC generated (at line 15, column 37) for  -x
      % expected type  real_abs_le1
  acos_neg_TCC1: OBLIGATION FORALL (x: real_abs_le1): -1 <= -x AND -x <= 1;

  % Subtype TCC generated (at line 17, column 37) for  sqrt(1 / 2)
      % expected type  real_abs_le1
  acos_sqrt_half_TCC1: OBLIGATION -1 <= sqrt(1 / 2) AND sqrt(1 / 2) <= 1;

  % Subtype TCC generated (at line 20, column 37) for  -sqrt(1 / 2)
      % expected type  real_abs_le1
  acos_minus_sqrt_half_TCC1: OBLIGATION
    -1 <= -sqrt(1 / 2) AND -sqrt(1 / 2) <= 1;

  % Subtype TCC generated (at line 25, column 11) for  nnx
      % expected type  real_abs_le1
  acos_sum_TCC1: OBLIGATION
    FORALL (nnx: {x: nnreal | x <= 1}): -1 <= nnx AND nnx <= 1;

  % Subtype TCC generated (at line 25, column 47) for  1 - sq(nny)
      % expected type  nnx: nonneg_real
  acos_sum_TCC2: OBLIGATION
    FORALL (nny: {x: nnreal | x <= 1}): 1 - sq(nny) >= 0;

  % Subtype TCC generated (at line 25, column 33) for
      % nnx * nny - (sqrt(1 - sq(nny))) * (sqrt(1 - sq(nnx)))
      % expected type  real_abs_le1
  acos_sum_TCC3: OBLIGATION
    FORALL (nnx, nny: {x: nnreal | x <= 1}):
      -1 <= nnx * nny - (sqrt(1 - sq(nny))) * (sqrt(1 - sq(nnx))) AND
       nnx * nny - (sqrt(1 - sq(nny))) * (sqrt(1 - sq(nnx))) <= 1;


body:
  taylor_help[T: TYPE FROM real]: THEORY
  BEGIN

      between(aa,bb:T): TYPE = {x: T | (aa < bb IMPLIES aa < x AND x < bb) AND
                                    (bb < aa  IMPLIES bb < x AND x < aa) AND
                                    (aa = bb IMPLIES x = aa)}


  END taylor_help


body:
  sincos_def: THEORY
  BEGIN

    IMPORTING reals@quadratic, reals@factorial, reals@sigma_nat
    IMPORTING trig_basic, taylor_help[real]

    x,x0:  VAR real
    px:    VAR posreal
    n:     VAR nat

    cos_ub: LEMMA cos(x)        <= 1
    sin_ub: AXIOM sin(px)       <  px
    cos_lb: AXIOM 1-px*px/2     <  cos(px)
    sin_lb: AXIOM px-px*px*px/6 <  sin(px)

    cos_pos_bnds:    LEMMA 1-px*px/2     < cos(px) AND cos(px) <= 1
    sin_pos_bnds:    LEMMA px-px*px*px/6 < sin(px) AND sin(px) <  px


    sin_series_term(x:real):[nat->real]
      = (LAMBDA (n:nat): (-1)^n*x^(2*n+1)/factorial(2*n+1))

    sin_series_n(x:real,n:nat):real
      = sigma(0,n,LAMBDA (i:nat): IF i>n THEN 0 ELSE sin_series_term(x)(i) ENDIF)

    cos_series_term(x:real):[nat->real]
      = (LAMBDA (n:nat): IF n=0 THEN 1 ELSE (-1)^n*x^(2*n)/factorial(2*n) ENDIF)

    cos_series_n(x:real,n:nat):real
      = sigma(0,n,LAMBDA (i:nat): IF i>n THEN 0 ELSE cos_series_term(x)(i) ENDIF)

    sin_series: AXIOM abs(sin(x)-sin_series_n(x,n))
                        <= abs(x^(2*n+3))/factorial(2*n+3)
    cos_series: AXIOM abs(cos(x)-cos_series_n(x,n))
                        <= abs(x^(2*n+2))/factorial(2*n+2)

    % THE FOLLOWING ARE IMPORTED TO MATCH trig_fnd
    IMPORTING asin, acos, atan
    a: VAR real

    sin_asin: AXIOM FORALL (x: trig_range): sin(asin(x)) = x
    cos_acos: AXIOM FORALL (x: trig_range): cos(acos(x)) = x
    tan_atan: AXIOM FORALL (x: trig_range): tan(atan(a)) = a

    asin_sin: AXIOM FORALL (x:real_abs_le_pi2): asin(sin(x)) = x
    acos_cos: AXIOM FORALL (x:nnreal_le_pi):   acos(cos(x)) = x
    atan_tan: AXIOM FORALL (x:real_abs_lt_pi2): atan(tan(x)) = x


  END sincos_def

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 21, column 33) for  (2 * n + 1)
      % expected type  {i: int | x /= 0 OR i >= 0}
  sin_series_term_TCC1: OBLIGATION
    FORALL (x: real, n: nat): x /= 0 OR (2 * n + 1) >= 0;

  % Subtype TCC generated (at line 24, column 14) for  n
      % expected type  T_high[nat]
  sin_series_n_TCC1: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);

  % Subtype TCC generated (at line 27, column 52) for  (2 * n)
      % expected type  {i: int | x /= 0 OR i >= 0}
  cos_series_term_TCC1: OBLIGATION
    FORALL (x: real, n: nat): NOT n = 0 IMPLIES x /= 0 OR (2 * n) >= 0;

  % Subtype TCC generated (at line 33, column 32) for  (2 * n + 3)
      % expected type  {i: int | x /= 0 OR i >= 0}
  sin_series_TCC1: OBLIGATION
    FORALL (n: nat, x: real): x /= 0 OR (2 * n + 3) >= 0;

  % Subtype TCC generated (at line 35, column 32) for  (2 * n + 2)
      % expected type  {i: int | x /= 0 OR i >= 0}
  cos_series_TCC1: OBLIGATION
    FORALL (n: nat, x: real): x /= 0 OR (2 * n + 2) >= 0;

  % Subtype TCC generated (at line 43, column 46) for  atan(a)
      % expected type  (Tan?)
  tan_atan_TCC1: OBLIGATION FORALL (a: real, x: trig_range): Tan?(atan(a));

  % Subtype TCC generated (at line 47, column 55) for  x
      % expected type  (Tan?)
  atan_tan_TCC1: OBLIGATION FORALL (x: real_abs_lt_pi2): Tan?(x);


body:
  sincos: THEORY

    BEGIN

    IMPORTING sincos_def
    IMPORTING analysis_ax@deriv_domains, analysis_ax@derivatives, analysis_ax@nth_derivatives, 
              analysis_ax@taylors


    x,x0:  VAR real
    px:    VAR posreal
    n:     VAR nat

  %   sin_convergence: LEMMA convergence(NQ(sin,x),0,cos(x))
     sin_derivable     : AXIOM derivable?(sin,x)
     sin_derivable_fun : LEMMA derivable?(sin)
     deriv_sin_fun     : AXIOM deriv(sin) = cos

  %   cos_convergence: LEMMA convergence(NQ(cos,x),0,-sin(x))
     cos_derivable     : AXIOM derivable?(cos,x)
     cos_derivable_fun : LEMMA derivable?(cos)
     deriv_cos_fun     : AXIOM deriv(cos) = -sin

     sin_continuous    : AXIOM continuous?(sin,x0)
     cos_continuous    : AXIOM continuous?(cos,x0)
     sin_continuous_fun: LEMMA continuous?(sin)
     cos_continuous_fun: LEMMA continuous?(cos)

     nderiv_sin_fun    : AXIOM derivable_n_times?(sin,n) AND
                            nderiv(n,sin) = LAMBDA (x:real): sin((n*pi/2)+x)
     nderiv_cos_fun    : AXIOM derivable_n_times?(cos,n) AND
                            nderiv(n,cos) = LAMBDA (x:real): cos((n*pi/2)+x)

     sin_taylors: LEMMA (EXISTS (c: between(0,x)): 
       sin(x) = sin_series_n(x,n)+nderiv(2*n+3,sin)(c)*x^(2*n+3)/factorial(2*n+3))

     cos_taylors: LEMMA (EXISTS (c: between(0,x)): 
       cos(x) = cos_series_n(x,n)+nderiv(2*n+2,cos)(c)*x^(2*n+2)/factorial(2*n+2))


    END sincos

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 30, column 12) for
      % analysis_ax@derivatives_def[real]
      % generated from assumption derivatives_def.deriv_domain
  sin_derivable_TCC1: OBLIGATION deriv_domain?[real];

  % Assuming TCC generated (at line 30, column 12) for
      % analysis_ax@derivatives_def[real]
      % generated from assumption derivatives_def.not_one_element
  sin_derivable_TCC2: OBLIGATION not_one_element?[real];

  % Subtype TCC generated (at line 17, column 35) for  sin
      % expected type  deriv_fun[real]
  deriv_sin_fun_TCC1: OBLIGATION derivable?[real](sin);

  % Subtype TCC generated (at line 22, column 35) for  cos
      % expected type  deriv_fun[real]
  deriv_cos_fun_TCC1: OBLIGATION derivable?[real](cos);

  % Subtype TCC generated (at line 35, column 45) for  sin
      % expected type  nderiv_fun[real](3 + 2 * n)
  sin_taylors_TCC1: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)):
      derivable_n_times?[real](sin, 3 + 2 * n);

  % Subtype TCC generated (at line 35, column 56) for  (2 * n + 3)
      % expected type  {i: int | x /= 0 OR i >= 0}
  sin_taylors_TCC2: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)):
      x /= 0 OR (2 * n + 3) >= 0;

  % Subtype TCC generated (at line 38, column 45) for  cos
      % expected type  nderiv_fun[real](2 + 2 * n)
  cos_taylors_TCC1: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)):
      derivable_n_times?[real](cos, 2 + 2 * n);

  % Subtype TCC generated (at line 38, column 56) for  (2 * n + 2)
      % expected type  {i: int | x /= 0 OR i >= 0}
  cos_taylors_TCC2: OBLIGATION
    FORALL (n: nat, x: real, c: between[real](0, x)):
      x /= 0 OR (2 * n + 2) >= 0;


body:
  deriv_sincos[ T : TYPE FROM real ] : THEORY
  %------------------------------------------------------------------------------
  %  Convenient forms of sin cos derivatives.
  %
  %      Rick Butler 4/1/2010
  %------------------------------------------------------------------------------
  BEGIN

     ASSUMING
       IMPORTING analysis_ax@deriv_domain

       connected_domain: ASSUMPTION connected?[T]

       not_one_element : ASSUMPTION not_one_element?[T]

     ENDASSUMING

     deriv_domain: LEMMA deriv_domain?[T]


     IMPORTING sincos, analysis_ax@chain_rule, analysis_ax@composition_continuous

     a,b,t: VAR T
     k,alpha: VAR real

     sin_continuous: LEMMA
         continuous?[T](LAMBDA (x: T): k * sin(alpha * x))

     cos_continuous: LEMMA
         continuous?[T](LAMBDA (x: T): k * cos(alpha * x))

     sin_derivable: LEMMA
         derivable?[T](LAMBDA (x: T): k * sin(alpha * x))

     cos_derivable: LEMMA
         derivable?[T](LAMBDA (x: T): k * cos(alpha * x))

     IMPORTING analysis_ax@derivatives_lam[T]

     deriv_sin: LEMMA alpha /= 0 IMPLIES
         deriv[T](LAMBDA (x:T): k*sin(alpha*x)) =  
              (LAMBDA (t: T): k*alpha*cos(alpha*t))
    
     deriv_cos: LEMMA alpha /= 0 IMPLIES
         deriv[T](LAMBDA (x:T): k*cos(alpha*x)) = 
              (LAMBDA (t: T): -k*alpha*sin(alpha*t))

  END deriv_sincos

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 24, column 4) for
      % analysis_ax@derivatives[T]
      % generated from assumption derivatives.deriv_domain
  sin_derivable_TCC1: OBLIGATION deriv_domain?[T];

  % Assuming TCC generated (at line 26, column 4) for
      % analysis_ax@derivatives[T]
      % generated from assumption derivatives.not_one_element
  sin_derivable_TCC2: OBLIGATION not_one_element?[T];

  % Subtype TCC generated (at line 41, column 16) for
      % LAMBDA (x: T): k * sin(alpha * x)
      % expected type  deriv_fun[T]
  deriv_sin_TCC1: OBLIGATION
    FORALL (alpha, k: real):
      alpha /= 0 IMPLIES derivable?[T](LAMBDA (x: T): k * sin(alpha * x));

  % Subtype TCC generated (at line 45, column 16) for
      % LAMBDA (x: T): k * cos(alpha * x)
      % expected type  deriv_fun[T]
  deriv_cos_TCC1: OBLIGATION
    FORALL (alpha, k: real):
      alpha /= 0 IMPLIES derivable?[T](LAMBDA (x: T): k * cos(alpha * x));


body:
  integral_indef_sincos[T: TYPE+ FROM real]: THEORY
  %------------------------------------------------------------------------------
  %
  %   Integration results for the kinematics library
  %
  %    Provides: the connection between the calculation of the position
  %              during a turn and the integration of speed values
  %
  %    Authors: Radu Siminiceanu    National Institute of Aerospace
  %             Rick Butler         NASA Langley
  %
  %------------------------------------------------------------------------------
  BEGIN

     ASSUMING
        IMPORTING analysis_ax@deriv_domain_def

        connected_domain : ASSUMPTION connected?[T]

        not_one_element : ASSUMPTION not_one_element?[T]

        T_pred0         : ASSUMPTION T_pred(0)

     ENDASSUMING

     IMPORTING sincos,
     	     deriv_sincos, 
  	     analysis_ax@fundamental_theorem,
  	     analysis_ax@chain_rule,
  	     analysis_ax@composition_continuous,
  	     analysis_ax@continuous_lambda,
  	     analysis_ax@derivatives_lam,
  	     analysis_ax@indefinite_integral
  	     

     alpha, theta, k, a, b, v: VAR real
     w : VAR nzreal
     t0, t1, t2: VAR T

     derivable_sin_lin: LEMMA a /=0 IMPLIES
     	derivable?(LAMBDA (t: T): k / a * sin(a*t + b))

     derivable_cos_lin: LEMMA a /=0 IMPLIES
     	derivable?(LAMBDA (t: T): k / a * cos(a*t + b))

     deriv_sin_lin: LEMMA a /= 0 IMPLIES
          deriv[T](LAMBDA (t: T): k*sin(b+a*t)) =  
               (LAMBDA (u: T): k*a*cos(b+a*u))
    
     deriv_cos_lin: LEMMA a /= 0 IMPLIES
          deriv[T](LAMBDA (t: T): -k*cos(b+a*t)) = 
               (LAMBDA (u: T): k*a*sin(b+a*u))

     cos_lin_integrable: LEMMA alpha /= 0 
                      IMPLIES integrable?[T](LAMBDA (t: T): k * cos(theta + alpha * t))

     sin_lin_integrable: LEMMA alpha /=0 
     		    IMPLIES integrable?[T](LAMBDA (t: T): k * sin(theta + alpha * t))

     integral_sin: LEMMA (EXISTS (c:real):
         integral[T](LAMBDA (t: T): v*sin(theta + w*t)) = (LAMBDA (t: T): -(v/w)*cos(theta + w*t)) + const_fun(c))

     integral_cos: LEMMA (EXISTS (c:real):
         integral[T](LAMBDA (t: T): v*cos(theta + w*t)) = (LAMBDA (t: T): (v/w)*sin(theta + w*t)) + const_fun(c))


     Integral_sin: LEMMA
     	Integral(t1, t2, (LAMBDA (t: T): v*sin(theta + w*t))) = -(v/w)*(cos(theta + w*t2) - cos(theta + w*t1))

     Integral_cos: LEMMA
     	Integral(t1, t2, (LAMBDA (t: T): v*cos(theta + w*t))) = (v/w)*(sin(theta + w*t2) - sin(theta + w*t1))
    
  END integral_indef_sincos

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 6, column 39) for
      % analysis_ax@derivatives[T]
      % generated from assumption derivatives.deriv_domain
  derivable_sin_lin_TCC1: OBLIGATION
    FORALL (a: real): a /= 0 IMPLIES deriv_domain?[T];

  % Assuming TCC generated (at line 6, column 39) for
      % analysis_ax@derivatives[T]
      % generated from assumption derivatives.not_one_element
  derivable_sin_lin_TCC2: OBLIGATION
    FORALL (a: real): a /= 0 IMPLIES not_one_element?[T];

  % Subtype TCC generated (at line 47, column 17) for
      % LAMBDA (t: T): k * sin(b + a * t)
      % expected type  deriv_fun[T]
  deriv_sin_lin_TCC1: OBLIGATION
    FORALL (a, b, k: real):
      a /= 0 IMPLIES derivable?[T](LAMBDA (t: T): k * sin(b + a * t));

  % Subtype TCC generated (at line 51, column 17) for
      % LAMBDA (t: T): -k * cos(b + a * t)
      % expected type  deriv_fun[T]
  deriv_cos_lin_TCC1: OBLIGATION
    FORALL (a, b, k: real):
      a /= 0 IMPLIES derivable?[T](LAMBDA (t: T): -k * cos(b + a * t));

  % Assuming TCC generated (at line 17, column 6) for
      % analysis_ax@indefinite_integral[T]
      % generated from assumption indefinite_integral.connected_domain
  cos_lin_integrable_TCC1: OBLIGATION
    FORALL (alpha: real): alpha /= 0 IMPLIES connected?[T];

  % Subtype TCC generated (at line 61, column 19) for
      % LAMBDA (t: T): v * sin(theta + w * t)
      % expected type  f: integrable_fun[T]
  integral_sin_TCC1: OBLIGATION
    FORALL (theta, v: real, w: nzreal):
      integrable?[T](LAMBDA (t: T): v * sin(theta + w * t));

  % Assuming TCC generated (at line 17, column 6) for
      % analysis_ax@indefinite_integral[T]
      % generated from assumption indefinite_integral.connected_domain
  integral_sin_TCC2: OBLIGATION connected?[T];

  % Assuming TCC generated (at line 20, column 6) for
      % analysis_ax@indefinite_integral[T]
      % generated from assumption indefinite_integral.not_one_element
  integral_sin_TCC3: OBLIGATION not_one_element?[T];

  % Subtype TCC generated (at line 64, column 19) for
      % LAMBDA (t: T): v * cos(theta + w * t)
      % expected type  f: integrable_fun[T]
  integral_cos_TCC1: OBLIGATION
    FORALL (theta, v: real, w: nzreal):
      integrable?[T](LAMBDA (t: T): v * cos(theta + w * t));

  % Subtype TCC generated (at line 68, column 22) for
      % (LAMBDA (t: T): v * sin(theta + w * t))
      % expected type  Integrable_funs[T](t1, t2)
  Integral_sin_TCC1: OBLIGATION
    FORALL (t1, t2: T, theta, v: real, w: nzreal):
      Integrable?[T](t1, t2, LAMBDA (t: T): v * sin(theta + w * t));

  % Subtype TCC generated (at line 71, column 22) for
      % (LAMBDA (t: T): v * cos(theta + w * t))
      % expected type  Integrable_funs[T](t1, t2)
  Integral_cos_TCC1: OBLIGATION
    FORALL (t1, t2: T, theta, v: real, w: nzreal):
      Integrable?[T](t1, t2, LAMBDA (t: T): v * cos(theta + w * t));


body:
  integral_sincos[T : TYPE+ FROM real ] : THEORY
  %------------------------------------------------------------------------------
  %  Convenient forms of sin cos integrals.
  %
  %      Rick Butler 4/1/2010
  %------------------------------------------------------------------------------
  BEGIN
     ASSUMING
       IMPORTING analysis_ax@deriv_domain

       connected_domain: ASSUMPTION connected?[T]

       not_one_element : ASSUMPTION not_one_element?[T]

     ENDASSUMING

     AUTO_REWRITE+ connected_domain
     AUTO_REWRITE+ not_one_element


     IMPORTING analysis_ax@deriv_domain, deriv_sincos[T], analysis_ax@fundamental_theorem[T]

     k,alpha: VAR real
     a,b: VAR T
    
     sin_Integrable: LEMMA
           Integrable?[T](a, b, LAMBDA (x: T): k * sin(alpha * x))

     cos_Integrable: LEMMA
           Integrable?[T](a, b, LAMBDA (x: T): k * cos(alpha * x))

     Integral_sin: LEMMA alpha /= 0 IMPLIES
           Integral[T](a,b, (LAMBDA (x:T): k*sin(alpha*x))) = -k/alpha*(cos(alpha*b) - cos(alpha*a)) 
   
    
     Integral_cos: LEMMA alpha /= 0 IMPLIES
           Integral[T](a,b, (LAMBDA (x:T): k*cos(alpha*x))) = k/alpha*(sin(alpha*b) - sin(alpha*a))


  END integral_sincos

addendum:
  %%% ================ Addendum: generated declarations ================

  % Assuming TCC generated (at line 21, column 39) for  deriv_sincos[T]
      % generated from assumption deriv_sincos.connected_domain
  IMP_deriv_sincos_TCC1: OBLIGATION connected?[T];

  % Assuming TCC generated (at line 21, column 39) for  deriv_sincos[T]
      % generated from assumption deriv_sincos.not_one_element
  IMP_deriv_sincos_TCC2: OBLIGATION not_one_element?[T];

  % Subtype TCC generated (at line 33, column 27) for
      % (LAMBDA (x: T): k * sin(alpha * x))
      % expected type  Integrable_funs[T](a, b)
  Integral_sin_TCC1: OBLIGATION
    FORALL (a: T, alpha: real, b: T, k: real):
      alpha /= 0 IMPLIES
       Integrable?[T](a, b, LAMBDA (x: T): k * sin(alpha * x));

  % Subtype TCC generated (at line 37, column 27) for
      % (LAMBDA (x: T): k * cos(alpha * x))
      % expected type  Integrable_funs[T](a, b)
  Integral_cos_TCC1: OBLIGATION
    FORALL (a: T, alpha: real, b: T, k: real):
      alpha /= 0 IMPLIES
       Integrable?[T](a, b, LAMBDA (x: T): k * cos(alpha * x));


body:
  trig_ineq: THEORY

    BEGIN

    IMPORTING trig_basic

    a,b  : VAR real
    n    : VAR int

  % ------------------- Sign of sin, cos, and tan  -----------------------

    cos_gt_0    : AXIOM -pi/2 < a  AND a <  pi/2   IMPLIES cos(a) >  0
    sin_gt_0    : LEMMA 0 < a      AND a <  pi     IMPLIES sin(a) >  0
    sin_ge_0    : LEMMA 0 <= a     AND a <= pi     IMPLIES sin(a) >= 0
    cos_ge_0    : LEMMA -pi/2 <= a AND a <= pi/2   IMPLIES cos(a) >= 0
    sin_lt_0    : LEMMA pi < a     AND a <  2*pi   IMPLIES sin(a) <  0
    cos_lt_0    : LEMMA pi/2 < a   AND a <  3*pi/2 IMPLIES cos(a) <  0
    sin_le_0    : LEMMA pi <= a    AND a <= 2*pi   IMPLIES sin(a) <= 0
    cos_le_0    : LEMMA pi/2 <= a  AND a <= 3*pi/2 IMPLIES cos(a) <= 0
    tan_gt_0    : LEMMA 0 < a      AND a <  pi/2   IMPLIES tan(a) >  0
    tan_lt_0    : LEMMA -pi/2 < a  AND a <  0      IMPLIES tan(a) <  0

    tan_pi2_def   : LEMMA  -pi/2 < a AND a < pi/2   IMPLIES Tan?(a) 
    tan_npi_def   : LEMMA Tan?(n*pi)
    cos_ge_0_3pi2 : LEMMA 3*pi/2 <= a AND a <= 2*pi IMPLIES cos(a) >= 0 

  % -------------------- Strict Inequalities --------------------

    sin_increasing_imp : LEMMA
                       a <= pi/2 AND a >= -pi/2 AND
                       b <= pi/2 AND b >= -pi/2 AND
                       a > b 
                       => 
                       sin(a) > sin(b)

    sin_increasing : LEMMA
                       a <= pi/2 AND a >= -pi/2 AND
                       b <= pi/2 AND b >= -pi/2 IMPLIES
                       (sin(a) > sin(b)
                       <=> 
                       a > b)

    sin_decreasing : LEMMA
                       a <= 3*pi/2 AND a >= pi/2 AND
                       b <= 3*pi/2 AND b >= pi/2 IMPLIES
                       (sin(b) > sin(a)
                       <=> 
                       a > b)


    cos_increasing : LEMMA
                       a >= pi AND a <= 2*pi AND
                       b >= pi AND b <= 2*pi IMPLIES
                       (cos(a) > cos(b)
                       <=> 
                       a > b)

    cos_decreasing : LEMMA
                       a <= pi AND a >= 0 AND
                       b <= pi AND b >= 0 IMPLIES
                       (cos(b) > cos(a)
                       <=> 
                       a > b)

    tan_increasing_imp: LEMMA
                        -pi/2 < a AND a < pi/2 AND
                        -pi/2 < b AND b < pi/2 AND
                         a > b IMPLIES
                         tan(a) > tan(b)

    tan_increasing : LEMMA
                       -pi/2 < a AND a < pi/2 AND
                       -pi/2 < b AND b < pi/2 IMPLIES
                           (tan(a) > tan(b) <=> a > b)
                        
  % -------------------- Non-Strict Inequalities --------------------

    sin_incr  : LEMMA  a <= pi/2 AND a >= -pi/2 AND
                       b <= pi/2 AND b >= -pi/2 IMPLIES
                       (sin(a) >= sin(b) <=> a >= b)

    sin_decr  : LEMMA  a <= 3*pi/2 AND a >= pi/2 AND
                       b <= 3*pi/2 AND b >= pi/2 IMPLIES
                       (sin(b) >= sin(a) <=> a >= b)

    cos_incr  : LEMMA  a >= pi AND a <= 2*pi AND
                       b >= pi AND b <= 2*pi IMPLIES
                       (cos(a) >= cos(b) <=> a >= b)

    cos_decr  : LEMMA  a <= pi AND a >= 0 AND
                       b <= pi AND b >= 0 IMPLIES
                       (cos(b) >= cos(a) <=> a >= b)

    tan_incr  : LEMMA  -pi/2 < a AND a < pi/2 AND
                       -pi/2 < b AND b < pi/2 IMPLIES
                       (tan(a) >= tan(b) <=> a >= b)

  % -------------------- Some properties about sin --------------------

    sin_gt : LEMMA
      -pi/2 <= a AND a < 3*pi/2 AND
      -pi/2 <= b AND b <= pi/2 IMPLIES
     (sin(a) > sin(b) IFF b < a AND a < pi-b)

    sin_lt : LEMMA
      -pi/2 <= a AND a < 3*pi/2 AND
      -pi/2 <= b AND b <= pi/2 IMPLIES
     (sin(a) < sin(b) IFF b > a OR a > pi-b)

    sin_ge : LEMMA
      -pi/2 <= a AND a < 3*pi/2 AND
      -pi/2 <= b AND b <= pi/2 IMPLIES
     (sin(a) >= sin(b) IFF b <= a AND a <= pi-b)


    END trig_ineq

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 20, column 61) for  a
      % expected type  (Tan?)
  tan_gt_0_TCC1: OBLIGATION
    FORALL (a: real): a < pi / 2 AND 0 < a IMPLIES Tan?(a);

  % Subtype TCC generated (at line 21, column 61) for  a
      % expected type  (Tan?)
  tan_lt_0_TCC1: OBLIGATION
    FORALL (a: real): a < 0 AND -pi / 2 < a IMPLIES Tan?(a);

  % Subtype TCC generated (at line 69, column 27) for  a
      % expected type  (Tan?)
  tan_increasing_imp_TCC1: OBLIGATION
    FORALL (a, b: real):
           a > b AND b < pi / 2 AND -pi / 2 < b AND a < pi / 2
       AND -pi / 2 < a
       IMPLIES Tan?(a);

  % Subtype TCC generated (at line 69, column 36) for  b
      % expected type  (Tan?)
  tan_increasing_imp_TCC2: OBLIGATION
    FORALL (a, b: real):
           a > b AND b < pi / 2 AND -pi / 2 < b AND a < pi / 2
       AND -pi / 2 < a
       IMPLIES Tan?(b);

  % Subtype TCC generated (at line 74, column 30) for  a
      % expected type  (Tan?)
  tan_increasing_TCC1: OBLIGATION
    FORALL (a, b: real):
      b < pi / 2 AND -pi / 2 < b AND a < pi / 2 AND -pi / 2 < a IMPLIES
       Tan?(a);

  % Subtype TCC generated (at line 74, column 39) for  b
      % expected type  (Tan?)
  tan_increasing_TCC2: OBLIGATION
    FORALL (a, b: real):
      b < pi / 2 AND -pi / 2 < b AND a < pi / 2 AND -pi / 2 < a IMPLIES
       Tan?(b);


body:
  atan2 : THEORY
  %-----------------------------------------------------------------------------
  %      atan2(x,y)
  %      ----
  %         - defines two-argument inverse tangent (arctangent): atan2
  %
  %      
  %-----------------------------------------------------------------------------
  BEGIN

    IMPORTING atan

    x,y,
    w,z   : VAR real
    a     : VAR {z:nnreal| z < 2*pi}
    nz    : VAR negreal
    pz    : VAR posreal

    %% Arc tangent of y/x taking into in account quadrants and indefinitions
    %% Polar angle of x + yI. 
    atan2(x:real,y:{z:real|x=0 => z/=0}): real
      = IF    x > 0 THEN IF y >= 0 THEN atan(y/x) ELSE 2*pi+atan(y/x) ENDIF
        ELSIF x = 0 THEN IF y >  0 THEN pi/2      ELSE 3*pi/2         ENDIF
                    ELSE pi + atan(y/x)                                    ENDIF

    atan2_0_2pi : LEMMA
      (x /= 0 OR y /= 0) IMPLIES
        (((x>=0 AND y>=0) => (0 <= atan2(x,y) AND atan2(x,y) <= pi/2))  AND
         ((x< 0 AND y>=0) => (pi/2 < atan2(x,y) AND atan2(x,y) <= pi)) AND
         ((x< 0 AND y< 0) => (pi < atan2(x,y)  AND atan2(x,y) < 3*pi/2)) AND
         ((x>=0 AND y< 0) => (3*pi/2 <= atan2(x,y)  AND atan2(x,y) < 2*pi)))

    atan2_ge_0_lt_2pi : LEMMA
      (x /= 0 OR y /= 0) IMPLIES
      atan2(x,y) >= 0 and
      atan2(x,y) < 2*pi

    nnreal_lt_2pi: NONEMPTY_TYPE = {x:nnreal | x < 2*pi} 

    JUDGEMENT atan2(x:real,y:{z:real|x=0 => z/=0}) HAS_TYPE nnreal_lt_2pi

    atan2_cancel_pos : LEMMA
      (x /= 0 OR y /= 0) IMPLIES atan2(x*pz,y*pz) = atan2(x,y)

    atan2_cancel_neg : LEMMA
      (x /= 0 OR y /= 0) IMPLIES
         atan2(x*nz,y*nz) =
             IF y > 0 OR (y = 0 AND x > 0) THEN atan2(x,y) + pi
                                           ELSE atan2(x,y) - pi ENDIF

    atan2_swap_pos : LEMMA
      x*y > 0 IMPLIES
      atan2(x,y) = atan2(y,x) + atan((y ^ 2 - x ^ 2) / (2 * (x * y)))

    atan2_swap_neg : LEMMA
      x*y < 0 IMPLIES
      atan2(x,y) =  atan2(y,x) + atan((y ^ 2 - x ^ 2) / (2 * (x * y))) + sign(x)*pi

    atan2_swap_zero : LEMMA
      (x = 0 AND y /= 0 IMPLIES
        atan2(x,y) = atan2(y,x) + pi/2) AND
      (y = 0 AND x /= 0 IMPLIES      
        atan2(x,y) = atan2(y,x) - pi/2)

    atan2_cos_sin : AXIOM
      atan2(cos(a),sin(a)) = a

    sin_atan2 : AXIOM
      (x /= 0 OR y /= 0) IMPLIES 
        sin(atan2(x,y)) = 
          IF x=0 THEN 
            IF y > 0 THEN 1 ELSE -1 ENDIF
          ELSE 
            LET yx = y/x IN 
            LET r = yx/sqrt((sq(yx)+1)) IN
              IF x > 0 THEN r
              ELSE -r
              ENDIF
          ENDIF

    cos_atan2 : AXIOM
      (x /= 0 OR y /= 0) IMPLIES
        cos(atan2(x,y)) = 
          IF x = 0 THEN 0 
          ELSE
            LET yx = y/x IN
            IF  x > 0 THEN 1/sqrt((sq(yx)+1)) 
            ELSE -1/sqrt((sq(yx)+1)) 
            ENDIF
          ENDIF

  END atan2

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 22, column 45) for  x
      % expected type  nznum
  atan2_TCC1: OBLIGATION
    FORALL (x: real, y: {z: real | x = 0 => z /= 0}):
      y >= 0 AND x > 0 IMPLIES x /= 0;

  % Subtype TCC generated (at line 22, column 65) for  x
      % expected type  nznum
  atan2_TCC2: OBLIGATION
    FORALL (x: real, y: {z: real | x = 0 => z /= 0}):
      NOT y >= 0 AND x > 0 IMPLIES x /= 0;

  % Subtype TCC generated (at line 24, column 35) for  x
      % expected type  nznum
  atan2_TCC3: OBLIGATION
    FORALL (x: real, y: {z: real | x = 0 => z /= 0}):
      NOT x = 0 AND NOT x > 0 IMPLIES x /= 0;

  % Subtype TCC generated (at line 28, column 41) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  atan2_0_2pi_TCC1: OBLIGATION
    FORALL (x, y: real):
      (x /= 0 OR y /= 0) AND y >= 0 AND x >= 0 IMPLIES x = 0 => y /= 0;

  % Subtype TCC generated (at line 29, column 43) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  atan2_0_2pi_TCC2: OBLIGATION
    FORALL (x, y: real):
      (x /= 0 OR y /= 0) AND
       ((x >= 0 AND y >= 0) => (0 <= atan2(x, y) AND atan2(x, y) <= pi / 2))
        AND y >= 0 AND x < 0
       IMPLIES x = 0 => y /= 0;

  % Subtype TCC generated (at line 30, column 41) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  atan2_0_2pi_TCC3: OBLIGATION
    FORALL (x, y: real):
           (x /= 0 OR y /= 0)
       AND ((x >= 0 AND y >= 0) =>
             (0 <= atan2(x, y) AND atan2(x, y) <= pi / 2))
       AND ((x < 0 AND y >= 0) =>
             (pi / 2 < atan2(x, y) AND atan2(x, y) <= pi))
       AND y < 0 AND x < 0
       IMPLIES x = 0 => y /= 0;

  % Subtype TCC generated (at line 31, column 46) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  atan2_0_2pi_TCC4: OBLIGATION
    FORALL (x, y: real):
           (x /= 0 OR y /= 0)
       AND ((x >= 0 AND y >= 0) =>
             (0 <= atan2(x, y) AND atan2(x, y) <= pi / 2))
       AND ((x < 0 AND y >= 0) =>
             (pi / 2 < atan2(x, y) AND atan2(x, y) <= pi))
       AND ((x < 0 AND y < 0) =>
             (pi < atan2(x, y) AND atan2(x, y) < 3 * pi / 2))
       AND y < 0 AND x >= 0
       IMPLIES x = 0 => y /= 0;

  % Subtype TCC generated (at line 35, column 12) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  atan2_ge_0_lt_2pi_TCC1: OBLIGATION
    FORALL (x, y: real): (x /= 0 OR y /= 0) IMPLIES x = 0 => y /= 0;

  % Existence TCC generated (at line 38, column 2) for
      % nnreal_lt_2pi: TYPE+ = {x: nnreal | x < 2 * pi}
  nnreal_lt_2pi_TCC1: OBLIGATION EXISTS (x1: {x: nnreal | x < 2 * pi}): TRUE;

  % Judgement subtype TCC generated (at line 40, column 12) for  atan2(x, y)
      % expected type  nnreal_lt_2pi
  atan2_TCC4: OBLIGATION
    FORALL (x: real, y: {z: real | x = 0 => z /= 0}):
      atan2(x, y) >= 0 AND atan2(x, y) < 2 * pi;

  % Subtype TCC generated (at line 43, column 42) for  y * pz
      % expected type  {z: real | x * pz = 0 => z /= 0}
  atan2_cancel_pos_TCC1: OBLIGATION
    FORALL (pz: posreal, x, y: real):
      (x /= 0 OR y /= 0) IMPLIES x * pz = 0 => y * pz /= 0;

  % Subtype TCC generated (at line 47, column 18) for  y * nz
      % expected type  {z: real | x * nz = 0 => z /= 0}
  atan2_cancel_neg_TCC1: OBLIGATION
    FORALL (nz: negreal, x, y: real):
      (x /= 0 OR y /= 0) IMPLIES x * nz = 0 => y * nz /= 0;

  % Subtype TCC generated (at line 53, column 12) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  atan2_swap_pos_TCC1: OBLIGATION
    FORALL (x, y: real): x * y > 0 IMPLIES x = 0 => y /= 0;

  % Subtype TCC generated (at line 53, column 40) for  2
      % expected type  {i: int | y /= 0 OR i >= 0}
  atan2_swap_pos_TCC2: OBLIGATION
    FORALL (x, y: real): x * y > 0 IMPLIES y /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 53, column 48) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  atan2_swap_pos_TCC3: OBLIGATION
    FORALL (x, y: real): x * y > 0 IMPLIES x /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 53, column 54) for  (2 * (x * y))
      % expected type  nznum
  atan2_swap_pos_TCC4: OBLIGATION
    FORALL (x, y: real): x * y > 0 IMPLIES (2 * (x * y)) /= 0;

  % Subtype TCC generated (at line 57, column 12) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  atan2_swap_neg_TCC1: OBLIGATION
    FORALL (x, y: real): x * y < 0 IMPLIES x = 0 => y /= 0;

  % Subtype TCC generated (at line 57, column 41) for  2
      % expected type  {i: int | y /= 0 OR i >= 0}
  atan2_swap_neg_TCC2: OBLIGATION
    FORALL (x, y: real): x * y < 0 IMPLIES y /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 57, column 49) for  2
      % expected type  {i: int | x /= 0 OR i >= 0}
  atan2_swap_neg_TCC3: OBLIGATION
    FORALL (x, y: real): x * y < 0 IMPLIES x /= 0 OR 2 >= 0;

  % Subtype TCC generated (at line 57, column 55) for  (2 * (x * y))
      % expected type  nznum
  atan2_swap_neg_TCC4: OBLIGATION
    FORALL (x, y: real): x * y < 0 IMPLIES (2 * (x * y)) /= 0;

  % Subtype TCC generated (at line 61, column 14) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  atan2_swap_zero_TCC1: OBLIGATION
    FORALL (x, y: real): y /= 0 AND x = 0 IMPLIES x = 0 => y /= 0;

  % Subtype TCC generated (at line 63, column 14) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  atan2_swap_zero_TCC2: OBLIGATION
    FORALL (x, y: real):
      (x = 0 AND y /= 0 IMPLIES atan2(x, y) = atan2(y, x) + pi / 2) AND
       x /= 0 AND y = 0
       IMPLIES x = 0 => y /= 0;

  % Subtype TCC generated (at line 66, column 17) for  sin(a)
      % expected type  {z: real | cos(a) = 0 => z /= 0}
  atan2_cos_sin_TCC1: OBLIGATION
    FORALL (a: {z: nnreal | z < 2 * pi}): cos(a) = 0 => sin(a) /= 0;

  % Subtype TCC generated (at line 74, column 21) for  x
      % expected type  nznum
  sin_atan2_TCC1: OBLIGATION
    FORALL (x, y: real): (x /= 0 OR y /= 0) AND NOT x = 0 IMPLIES x /= 0;


body:
  to2pi :THEORY
  BEGIN

    IMPORTING atan2, 
              trig_ineq,
  	    reals@abs_lems

    a,b   : VAR real
    alpha : VAR nnreal_lt_2pi
    beta  : VAR real
    k     : VAR int

    to2pi(a) : nnreal_lt_2pi =
      LET n = floor(a/(2*pi)) IN
      a - 2*n*pi

    to2pi_id : LEMMA
      to2pi(alpha) = alpha

    to2pi_period : LEMMA
      to2pi(a) = to2pi(a+2*k*pi)

    sin_id_to2pi : LEMMA
      sin(to2pi(a)) = sin(a)

    cos_id_to2pi : LEMMA
      cos(to2pi(a)) = cos(a)

    to2pi_to2pi : LEMMA
      to2pi(to2pi(a)+b) = to2pi(a+b)

    to2pi_to2pi_sub : LEMMA
      to2pi(b-to2pi(a)) = to2pi(b-a)

    to2pi_neg : LEMMA
      -2*pi <= a AND a < 0 IMPLIES to2pi(a) = a+2*pi

    to2pi_equal : LEMMA
      to2pi(a) = to2pi(b) IMPLIES
        EXISTS(k:int): a = b + k*2*pi

    to2pi_to2pi_add : LEMMA
      to2pi(to2pi(a)+b) = to2pi(a+b)

    to2pi_closed_diff :  LEMMA
      abs(to2pi(a) - to2pi(b)) < 2*pi

    to2pi_eq: LEMMA
      FORALL (k: int): a = b + 2*k*pi IMPLIES
      to2pi(a) = to2pi(b)

    to2pi_sep : LEMMA
      a < b AND b < a + 2*pi IMPLIES 
      ((EXISTS (k:int): (a < 2*k*pi AND 2*k*pi <= b))
       OR
       (EXISTS (k: int): (2*k*pi <= a AND b < 2*(k+1)*pi)))

    sin_gt_to2pi : LEMMA
      -pi/2 <= b AND b <= pi/2 IMPLIES
     (sin(a) > sin(b) IFF b < to2pi(a+pi/2)-pi/2 AND to2pi(a+pi/2)-pi/2 < pi-b)

    sin_lt_to2pi : LEMMA
      -pi/2 <= b AND b <= pi/2 IMPLIES
     (sin(a) < sin(b) IFF b > to2pi(a+pi/2)-pi/2 OR to2pi(a+pi/2)-pi/2 > pi-b)

    sin_ge_to2pi : LEMMA
      -pi/2 <= b AND b <= pi/2 IMPLIES
     (sin(a) >= sin(b) IFF b <= to2pi(a+pi/2)-pi/2 AND to2pi(a+pi/2)-pi/2 <= pi-b)

    cos_pos_to2pi : LEMMA
      cos(a) > 0 IFF -pi/2 < to2pi(a+pi/2)-pi/2 AND to2pi(a+pi/2)-pi/2 < pi/2

    cos_nneg_to2pi : LEMMA
      cos(a) >= 0 IFF -pi/2 <= to2pi(a+pi/2)-pi/2 AND to2pi(a+pi/2)-pi/2 <= pi/2

  END to2pi

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 15, column 4) for  a - 2 * n * pi
      % expected type  nnreal_lt_2pi
  to2pi_TCC1: OBLIGATION
    FORALL (a: real, n: {i | i <= a / (2 * pi) & a / (2 * pi) < 1 + i}):
      n = floor(a / (2 * pi)) IMPLIES
       a - 2 * n * pi >= 0 AND a - 2 * n * pi < 2 * pi;


body:
  trig_inverses: THEORY
  %----------------------------------------------------------------------------
  % Interface to Inverse Trig Function
  %
  % Rick Butler 1/8/08
  %----------------------------------------------------------------------------
  BEGIN
     IMPORTING trig_basic, asin, acos, atan, atan2

    a: VAR real

    atan_prep: LEMMA FORALL (x: real_abs_lt_pi2): Tan?(x);

  % nnreal_quad1_closed: NONEMPTY_TYPE = {x:nnreal | x <= pi/2} 
  % nnreal_quad1_open:   NONEMPTY_TYPE = {x:nnreal | x <  pi/2} 
  % real_abs_lt_pi:      NONEMPTY_TYPE = {x:real   | -pi/2 < x AND x < pi/2} 
  % posreal_lt_pi:       NONEMPTY_TYPE = {x:posreal| x < pi} 
  % nnreal_le_pi :       NONEMPTY_TYPE = {x:nnreal | x <= pi}     
  % real_abs_le1:        NONEMPTY_TYPE = {x:real | -1 <= x AND x <= 1}    
  % real_abs_lt1:        NONEMPTY_TYPE = {x:real | -1 < x  AND x <  1}    
  % real_abs_le_pi2:     NONEMPTY_TYPE = {x:real | -pi/2 <= x AND x <= pi/2}


  % ---------- ArcSine ----------------- (See asin.pvs)
  %
  %   asin(x:real_abs_le1): real_abs_le_pi2
  %
  %   asin_0:                 LEMMA asin(0)  = 0
  %   asin_sqrt_half:         LEMMA asin(sqrt(1/2)) = pi/4
  %   asin_1:                 LEMMA asin(1)  = pi/2
  %   asin_neg:               LEMMA asin(-x) = -asin(x)
  %   asin_minus1:            LEMMA asin(-1) = -pi/2
  %   asin_minus_sqrt_half:   LEMMA asin(-sqrt(1/2)) = -pi/4

      AUTO_REWRITE+ asin_0
      AUTO_REWRITE+ asin_1

  % ---------- ArcCosine ----------------- (See acos.pvs)
  %
  %   acos(x:real_abs_le1): nnreal_le_pi = pi/2 - asin(x)
  %
  %   acos_neg:               LEMMA acos(-x) = pi-acos(x)
  %   acos_0:                 LEMMA acos(0)  = pi/2
  %   acos_sqrt_half:         LEMMA acos(sqrt(1/2)) = pi/4
  %   acos_1:                 LEMMA acos(1)  = 0
  %   acos_minus1:            LEMMA acos(-1) = pi
  %   acos_minus_sqrt_half:   LEMMA acos(-sqrt(1/2)) = 3*pi/4

      AUTO_REWRITE+ acos_0
      AUTO_REWRITE+ acos_1


  % ---------- ArcTangent ----------------- (See atan.pvs)
  %
  %  atan(x:real): real_abs_lt_pi2 
  %
  %  atan_0                : LEMMA atan(0) = 0
  %  atan_inv              : LEMMA atan(1/px) = pi/2-atan(px)
  %  atan_inv_neg          : LEMMA atan(1/nx) = -pi/2-atan(nx)
  %  atan_neg              : LEMMA atan(-x)   = -atan(x) 
  %  acot_neg              : LEMMA acot(-nzx) = -acot(nzx)  

      AUTO_REWRITE+ atan_0

  %  --------- Inverse Relationships (From sincos_def)

     x: VAR trig_range
     sin_asin: AXIOM sin(asin(x)) = x
     cos_acos: AXIOM cos(acos(x)) = x
     tan_atan: AXIOM tan(atan(a)) = a

     asin_sin: AXIOM FORALL (x:real_abs_le_pi2): asin(sin(x)) = x
     acos_cos: AXIOM FORALL (x:nnreal_le_pi):   acos(cos(x)) = x
     atan_tan: AXIOM FORALL (x:real_abs_lt_pi2): atan(tan(x)) = x


  %  --- The following provide additional names for the inverse functions
  %  --- that include their basic property in the type.  These are included
  %  --- for upward compatibility.

  %  -------------------- Arcsin --------------------

     arcsin(y: real_abs_le1): {x: real_abs_le_pi2 | y = sin(x)} = asin(y)

     sin_arcsin: AXIOM (FORALL (y: real_abs_le1): sin(arcsin(y)) = y)
     arcsin_sin: AXIOM (FORALL (x: real_abs_lt_pi2): arcsin(sin(x)) = x)

  %  -------------------- Arccos --------------------

     arccos(y: real_abs_le1): {x: nnreal_le_pi | y = cos(x)} = acos(y)

     cos_arccos: AXIOM (FORALL (y: real_abs_le1): cos(arccos(y)) = y)
     arccos_cos: AXIOM (FORALL (x: nnreal_le_pi): arccos(cos(x)) = x)

  %  -------------------- Arctan --------------------
     
     arctan_prep: LEMMA FORALL (x: real_abs_lt_pi2): Tan?(x);

     arctan(y: real): {x: real_abs_lt_pi2 | y = tan(x)} = atan(y)

     tan_arctan: AXIOM (FORALL (y: real): tan(arctan(y)) = y)
     arctan_tan: AXIOM (FORALL (x: real_abs_lt_pi2): arctan(tan(x)) = x)

  END trig_inverses

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 70, column 23) for  atan(a)
      % expected type  (Tan?)
  tan_atan_TCC1: OBLIGATION FORALL (a: real): Tan?(atan(a));

  % Subtype TCC generated (at line 74, column 56) for  x
      % expected type  (Tan?)
  atan_tan_TCC1: OBLIGATION FORALL (x: real_abs_lt_pi2): Tan?(x);

  % Subtype TCC generated (at line 83, column 64) for  asin(y)
      % expected type  {x: real_abs_le_pi2 | y = sin(x)}
  arcsin_TCC1: OBLIGATION FORALL (y: real_abs_le1): y = sin(asin(y));

  % Subtype TCC generated (at line 90, column 61) for  acos(y)
      % expected type  {x: nnreal_le_pi | y = cos(x)}
  arccos_TCC1: OBLIGATION FORALL (y: real_abs_le1): y = cos(acos(y));

  % Subtype TCC generated (at line 99, column 56) for  atan(y)
      % expected type  {x: real_abs_lt_pi2 | y = tan(x)}
  arctan_TCC1: OBLIGATION FORALL (y: real): y = tan(atan(y));

  % Subtype TCC generated (at line 101, column 44) for  arctan(y)
      % expected type  (Tan?)
  tan_arctan_TCC1: OBLIGATION FORALL (y: real): Tan?(arctan(y));


body:
  trig_values : THEORY
  %-----------------------------------------------------------------------------
  %      trig_values                            Lemma names
  %      -----------                   ------------------------------------
  %         - trig functions at 0      : sin_0     , cos_0     , tan_0 
  %         - trig functions at pi/6   : sin_pi6   , cos_pi6   , tan_pi6 
  %         - trig functions at pi/4   : sin_pi4   , cos_pi4   , tan_pi4 
  %         - trig functions at pi/3   : sin_pi3   , cos_pi3   , tan_pi3 
  %         - trig functions at pi/2   : sin_pi2   , cos_pi2   , tan_pi2 
  %         - trig functions at pi     : sin_pi    , cos_pi    , tan_pi 
  %         - trig functions at 2*pi/3 : sin_2pi3  , cos_2pi3  , tan_2pi3 
  %         - trig functions at 3*pi/4 : sin_3pi4  , cos_3pi4  , tan_3pi4 
  %         - trig functions at 5*pi/4 : sin_5pi4  , cos_5pi4  , tan_5pi4 
  %
  %      Version 1.1 Foundational (DRL) 27/10/03
  %
  %-----------------------------------------------------------------------------
  BEGIN

    IMPORTING trig_ineq

    a,b  : VAR real

    sin_cos_pi4 : LEMMA sin(pi/4) = cos(pi/4)
    cos_pi4     : LEMMA cos(pi/4) = 1/sqrt(2)
    sin_pi4     : LEMMA sin(pi/4) = 1/sqrt(2)
    cos_3pi4    : LEMMA cos(3*pi/4) = - 1/sqrt(2) 
    sin_3pi4    : LEMMA sin(3*pi/4) = 1/ sqrt(2)
    tan_pi4     : LEMMA tan(pi/4) = 1 

    sin_pi3_cos_pi6 : LEMMA sin(pi/3) = cos(pi/6)
    sin_pi6_cos_pi3 : LEMMA sin(pi/6) = cos(pi/3)

    sin_pi6     : LEMMA sin(pi/6) = 1/2
    cos_pi6     : LEMMA cos(pi/6) = sqrt(3)/2
    tan_pi6     : LEMMA tan(pi/6) = 1/sqrt(3)

    sin_pi3     : LEMMA sin(pi/3) = sqrt(3)/2
    cos_pi3     : LEMMA cos(pi/3) = 1/2
    tan_pi3     : LEMMA tan(pi/3) = sqrt(3)


    sin_2pi3     : LEMMA sin(2*pi/3) = sqrt(3)/2
    cos_2pi3     : LEMMA cos(2*pi/3) = -1/2
    tan_2pi3     : LEMMA tan(2*pi/3) = -sqrt(3)

    cos_5pi4     : LEMMA cos(5*pi/4) = - 1/sqrt(2)
    sin_5pi4     : LEMMA sin(5*pi/4) = - 1/sqrt(2)
    sin_cos_5pi4 : LEMMA sin(5*pi/4) = cos(5*pi/4)

  % ---------- The following are included for easy reference ---------
  %            They are all from "trig"            

  %  cos_0       : LEMMA cos(0) = 1 
  %  sin_0       : LEMMA sin(0) = 0
  %  sin_pi2     : LEMMA sin(pi/2) = 1
  %  cos_pi2     : LEMMA cos(pi/2) = 0
  %  tan_0       : LEMMA tan(0)=0

  %  sin_pi      : LEMMA sin(pi) = 0
  %  cos_pi      : LEMMA cos(pi) = -1
  %  tan_pi      : LEMMA tan(pi) = 0
  %  sin_3pi2    : LEMMA sin(3*pi/2) = -1
  %  cos_3pi2    : LEMMA cos(3*pi/2) = 0
  %  sin_2pi     : LEMMA sin(2*pi) = 0
  %  cos_2pi     : LEMMA cos(2*pi) = 1
  %  tan_2pi     : LEMMA tan(2*pi) = 0

  END trig_values

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 29, column 26) for  pi / 4
      % expected type  (Tan?)
  tan_pi4_TCC1: OBLIGATION Tan?(pi / 4);

  % Subtype TCC generated (at line 36, column 26) for  pi / 6
      % expected type  (Tan?)
  tan_pi6_TCC1: OBLIGATION Tan?(pi / 6);

  % Subtype TCC generated (at line 40, column 26) for  pi / 3
      % expected type  (Tan?)
  tan_pi3_TCC1: OBLIGATION Tan?(pi / 3);

  % Subtype TCC generated (at line 45, column 27) for  2 * pi / 3
      % expected type  (Tan?)
  tan_2pi3_TCC1: OBLIGATION Tan?(2 * pi / 3);


body:
  atan_values: THEORY
  %------------------------------------------------------------------------------
  %
  %  Rick Butler    NASA Langley
  % 
  %------------------------------------------------------------------------------
  BEGIN

    IMPORTING atan, trig_values, trig_inverses

    atan0        : LEMMA atan(0) = 0                   %% atan_0 already used

    atan1        : LEMMA atan(1) = pi/4                %% atan_1 already used

    atan_1sqrt3  : LEMMA atan(1/sqrt(3)) = pi/6

    atan_sqrt3   : LEMMA atan(sqrt(3))   = pi/3

    atan_m1sqrt3 : LEMMA atan(-1/sqrt(3)) = -pi/6

    atan_msqrt3  : LEMMA atan(-sqrt(3))   = -pi/3

    
    x: VAR real
    atan_gt_0    : LEMMA atan(x) > 0 IFF x > 0


  END atan_values


body:
  atan2_props: THEORY
  BEGIN

    IMPORTING atan2, trig_ineq

    atan2_is_0:    LEMMA FORALL (x:real,y:{z:real | x = 0 => z/=0}):
                             atan2(x,y) =   0    IFF (x > 0 AND y = 0)

    atan2_is_pi2:  LEMMA FORALL (x:real,y:{z:real | x = 0 => z/=0}):
                             atan2(x,y) =   pi/2 IFF (x = 0 AND y > 0)

    atan2_is_pi:   LEMMA FORALL (x:real,y:{z:real | x = 0 => z/=0}):
                             atan2(x,y) =   pi   IFF (x < 0 AND y = 0)

    atan2_is_3pi2: LEMMA FORALL (x:real,y:{z:real | x = 0 => z/=0}):
                             atan2(x,y) = 3*pi/2 IFF (x = 0 AND y < 0)

    atan2_quad1:   LEMMA FORALL (x:real,y:{z:real | x = 0 => z/=0}):
                             (0 < atan2(x,y) AND atan2(x,y) < pi/2) IFF
                                                                (x > 0 AND y > 0)

    atan2_quad2:   LEMMA FORALL (x:real,y:{z:real | x = 0 => z/=0}):
                             (pi/2 < atan2(x,y) AND atan2(x,y) < pi) IFF
                                                                (x < 0 AND y > 0)

    atan2_quad3:   LEMMA FORALL (x:real,y:{z:real | x = 0 => z/=0}):
                             (pi < atan2(x,y) AND atan2(x,y) < 3*pi/2) IFF
                                                                (x < 0 AND y < 0)

    atan2_quad4:   LEMMA FORALL (x:real,y:{z:real | x = 0 => z/=0}):
                             (3*pi/2 < atan2(x,y) AND atan2(x,y) < 2*pi) IFF
                                                                (x > 0 AND y < 0)

    %% ------------ atan2 values -------------------------------------


     IMPORTING trig_values, atan_values

     nzx: VAR nzreal

     atan2_0x      : LEMMA atan2(0,nzx) = IF nzx > 0 THEN pi/2 ELSE 3*pi/2 ENDIF
     atan2_x0      : LEMMA atan2(nzx,0) = IF nzx > 0 THEN 0 ELSE pi ENDIF

     atan2_11      : LEMMA atan2(1,1) = pi/4
     atan2_m11     : LEMMA atan2(-1,1) = 3*pi/4
     atan2_1m1     : LEMMA atan2(1,-1) = 7*pi/4
     atan2_m1m1    : LEMMA atan2(-1,-1) = 5*pi/4


     atan2_1sqrt3  : LEMMA atan2(1,sqrt(3)) = pi/3
     atan2_sqrt3   : LEMMA atan2(sqrt(3),1) = pi/6


     atan2_m1sqrt3 : LEMMA atan2(-1,sqrt(3)) = 2*pi/3
     atan2_sqrt3m1 : LEMMA atan2(sqrt(3),-1) = 11*pi/6


  END atan2_props

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 42, column 35) for  0
      % expected type  {z: real | nzx = 0 => z /= 0}
  atan2_x0_TCC1: OBLIGATION FORALL (nzx: nzreal): nzx = 0 => 0 /= 0;

  % Subtype TCC generated (at line 51, column 39) for  1
      % expected type  {z: real | sqrt(3) = 0 => z /= 0}
  atan2_sqrt3_TCC1: OBLIGATION sqrt(3) = 0 => 1 /= 0;

  % Subtype TCC generated (at line 55, column 39) for  -1
      % expected type  {z: real | sqrt(3) = 0 => z /= 0}
  atan2_sqrt3m1_TCC1: OBLIGATION sqrt(3) = 0 => -1 /= 0;


body:
  %------------------------------------------------------------------------------
  % Java atan2  --> (-pi, pi)
  %
  % Java atan2(y,x) converts rectangular coordinates (x,y) to polar (r,?),
  % where r is the distance from the origin and ? is the angle from the x-axis.
  % The equation for determining atan2 is: tan? = y / x (where ? is the angle).
  % The output values are in the range between -pi and pi
  %------------------------------------------------------------------------------
  jatan2: THEORY
  BEGIN
   
      IMPORTING trig_values, trig_inverses,  atan2_props
    
      x,y: VAR real

      jatan2(y:real,x:{z:real|y=0 => z/=0}): real = IF y >= 0 THEN atan2(x,y)
                                                    ELSE atan2(x,y) - 2*pi
                                                    ENDIF


  %%  TEST

      t1: LEMMA jatan2(1,1) = pi/4
      t2: LEMMA jatan2(-1,1) = -pi/4
      t3: LEMMA jatan2(1,-1) = 3*pi/4
      t4: LEMMA jatan2(-1,-1) = -3*pi/4

  END jatan2

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 16, column 73) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  jatan2_TCC1: OBLIGATION
    FORALL (y: real, x: {z: real | y = 0 => z /= 0}):
      y >= 0 IMPLIES x = 0 => y /= 0;

  % Subtype TCC generated (at line 17, column 63) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  jatan2_TCC2: OBLIGATION
    FORALL (y: real, x: {z: real | y = 0 => z /= 0}):
      NOT y >= 0 IMPLIES x = 0 => y /= 0;


body:
  trig_rew: THEORY
  BEGIN
  %-----------------------------------------------------------------------------
  %
  %  Experimental auto-rewrite-theory background trigonometry library
  %
  %  Users should be able to issue
  %
  %        (auto-rewrite_theory "trig_rew")
  %
  %  at the beginning of a proof to automatically simplify formulas
  %
  %-----------------------------------------------------------------------------

    IMPORTING trig_basic

    a,b,c,d           : VAR real
    nnc               : VAR nonneg_real 
    j,k,kk            : VAR integer
    n: VAR nat

  %  cos2         : LEMMA sq(cos(a)) = 1 - sq(sin(a)) 

    tr_rew1  : LEMMA cos(0) = 1 
    tr_rew2  : LEMMA sin(0) = 0
    tr_rew3  : LEMMA sin(pi/2) = 1
    tr_rew4  : LEMMA cos(pi/2) = 0
    tr_rew5  : LEMMA tan(0)=0
    tr_rew6  : LEMMA sin(pi) = 0
    tr_rew7  : LEMMA cos(pi) = -1
    tr_rew8  : LEMMA tan(pi) = 0
    tr_rew9  : LEMMA sin(3*pi/2) = -1
    tr_rew10 : LEMMA cos(3*pi/2) = 0
    tr_rew11 : LEMMA sin(2*pi) = 0
    tr_rew12 : LEMMA cos(2*pi) = 1
    tr_rew13 : LEMMA tan(2*pi) = 0
   
    tr_rew14 : LEMMA sin(pi/2 - a) = cos(a)
    tr_rew15 : LEMMA cos(pi/2 - a) = sin(a)

    tr_rew16 : LEMMA sin(k*pi) = 0
    tr_rew17 : LEMMA cos(2*k*pi) = 1
  %  tr_rew18 : LEMMA cos(k*pi) = (-1)^(k)
  %  tr_rew19 : LEMMA sin(k*pi + pi/2) = (-1)^k 
    tr_rew20 : LEMMA tan(k*pi) = 0

    tr_rew22 : LEMMA sin(-a) = -sin(a) 
    tr_rew23 : LEMMA cos(-a) = cos(a) 
    tr_rew24 : LEMMA FORALL(a:(Tan?)): tan(-a) = -tan(a)
   
  END trig_rew

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 28, column 23) for  0
      % expected type  (Tan?)
  tr_rew5_TCC1: OBLIGATION Tan?(0);

  % Subtype TCC generated (at line 31, column 23) for  pi
      % expected type  (Tan?)
  tr_rew8_TCC1: OBLIGATION Tan?(pi);

  % Subtype TCC generated (at line 36, column 23) for  2 * pi
      % expected type  (Tan?)
  tr_rew13_TCC1: OBLIGATION Tan?(2 * pi);

  % Subtype TCC generated (at line 45, column 23) for  k * pi
      % expected type  (Tan?)
  tr_rew20_TCC1: OBLIGATION FORALL (k: integer): Tan?(k * pi);

  % Subtype TCC generated (at line 49, column 41) for  -a
      % expected type  (Tan?)
  tr_rew24_TCC1: OBLIGATION FORALL (a: (Tan?)): Tan?(-a);


body:
  atan_approx: THEORY
  %-----------------------------------------------------------------------------
  %      atan_approx by David Lester
  %      -----------
  %      Defines upper and lower bounds on atan and pi:
  %           - atan_lb(a,n) <= atan(a) <= atan_ub(a,n)
  %           - pi_lb(a,n) <= pi <= pi_ub(n)
  %
  %-----------------------------------------------------------------------------
    BEGIN

    IMPORTING atan

    m,n:  VAR nat
    x:  VAR real
    px: VAR posreal

    atan_pos_le1_ub(n,x): real = atan_series_n(x,2*n)
    atan_pos_le1_lb(n,x): real = atan_series_n(x,2*n+1)

    atan_pos_le1_ub_lt : LEMMA
      0 < x AND x <= 1 IMPLIES
      atan_pos_le1_ub(n+1,x) < atan_pos_le1_ub(n,x)

    atan_pos_le1_lb_lt : LEMMA
      0 < x AND x <= 1 IMPLIES
      atan_pos_le1_lb(n,x) < atan_pos_le1_lb(n+1,x)

    atan_pos_le1_bounds: AXIOM 0 < x AND x <= 1 IMPLIES
      (atan_pos_le1_lb(n,x) < atan(x) AND atan(x) < atan_pos_le1_ub(n,x))

    atan_pos_le1_lb_inc: LEMMA px <= 1 AND n < m =>
                               atan_pos_le1_lb(n,px) < atan_pos_le1_lb(m,px)

    atan_pos_le1_ub_dec: LEMMA px <= 1 AND n < m =>
                               atan_pos_le1_ub(m,px) < atan_pos_le1_ub(n,px)

    pi_lbn(n): real = 4*(4*atan_pos_le1_lb(n,1/5) - atan_pos_le1_ub(n,1/239))
    pi_ubn(n): real = 4*(4*atan_pos_le1_ub(n,1/5) - atan_pos_le1_lb(n,1/239))


    pi_lbn_lt : LEMMA
      pi_lbn(n) < pi_lbn(n+1)

    pi_lbn_LT : LEMMA
      FORALL (k:above(n)):
        pi_lbn(n) < pi_lbn(k)

    pi_bounds: AXIOM pi_lbn(n) < pi AND pi < pi_ubn(n)

    pi_lb_pos : JUDGEMENT
      pi_lbn(n) HAS_TYPE posreal 

    pi_ub_pos : JUDGEMENT
      pi_ubn(n) HAS_TYPE posreal 

    pi_bounds0: LEMMA pi_lbn(0) = 281476/89625 AND    % > 3.1405
                      pi_ubn(0) = 651864872/204778785 % < 3.1837



  %  pi_lb : posreal = 31415926/10000000

  %  pi_ub : posreal = 31415927/10000000

    pi_bounds2: LEMMA pi_lb < pi_lbn(2) AND pi_ubn(2) < pi_ub

    pi_bound : JUDGEMENT pi HAS_TYPE {r:posreal | pi_lb < r AND r < pi_ub}

    pi_lb_inc: LEMMA n < m => pi_lbn(n) < pi_lbn(m)

    pi_ub_dec: LEMMA n < m => pi_ubn(m) < pi_ubn(n)



    atan_pos_lb(n,px): real = IF px <= 1 THEN atan_pos_le1_lb(n,px) ELSE
                              pi_lbn(n)/2 - atan_pos_le1_ub(n,1/px) ENDIF

    atan_pos_ub(n,px): real = IF px <= 1 THEN atan_pos_le1_ub(n,px) ELSE
                              pi_ubn(n)/2 - atan_pos_le1_lb(n,1/px) ENDIF

    atan_pos_bounds: LEMMA 0 < x IMPLIES
      (atan_pos_lb(n,x) < atan(x) AND atan(x) < atan_pos_ub(n,x))

    atan_lb(x,n): real = IF    x > 0 THEN atan_pos_lb(n,x)
                         ELSIF x = 0 THEN 0
                                     ELSE -atan_pos_ub(n,-x) ENDIF

    atan_ub(x,n): real = IF    x > 0 THEN atan_pos_ub(n,x)
                         ELSIF x = 0 THEN 0
                                     ELSE -atan_pos_lb(n,-x) ENDIF

    atan_bounds: LEMMA atan_lb(x,n) <= atan(x) AND atan(x) <= atan_ub(x,n)

    atan_pos_lb_inc: LEMMA n < m => atan_pos_lb(n,px) < atan_pos_lb(m,px)

    atan_pos_ub_dec: LEMMA n < m => atan_pos_ub(m,px) < atan_pos_ub(n,px)

    pi_lb_pi: AXIOM pi-pi_lbn(n) <= 16*((1/5)^(4*n+5)/(4*n+5)) +
                                    4*((1/239)^(4*n+3)/(4*n+3))

    pi_ub_pi: AXIOM pi_ubn(n)-pi <= 16*((1/5)^(4*n+3)/(4*n+3)) +
                                    4*((1/239)^(4*n+5)/(4*n+5))

    pi_lb_diff: LEMMA pi_lbn(n+1)-pi_lbn(n) = 
                      16*(1/5)^(4*n+5)*(1/(4*n+5) - 1/(25*(4*n+7))) +
                      4*(1/239)^(4*n+3)*(1/(4*n+3) - 1/(57121*(4*n+5)))


  END atan_approx

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 52, column 4) for  pi_lbn(n)
      % expected type  posreal
  pi_lb_pos: OBLIGATION FORALL (n): pi_lbn(n) >= 0 AND pi_lbn(n) > 0;

  % Judgement subtype TCC generated (at line 55, column 4) for  pi_ubn(n)
      % expected type  posreal
  pi_ub_pos: OBLIGATION FORALL (n): pi_ubn(n) >= 0 AND pi_ubn(n) > 0;

  % Judgement subtype TCC generated (at line 68, column 23) for  pi
      % expected type  {r: posreal | pi_lb < r AND r < pi_ub}
  pi_bound: OBLIGATION pi_lb < pi AND pi < pi_ub;

  % Subtype TCC generated (at line 83, column 19) for  x
      % expected type  posreal
  atan_pos_bounds_TCC1: OBLIGATION
    FORALL (x: real): 0 < x IMPLIES x >= 0 AND x > 0;

  % Subtype TCC generated (at line 85, column 54) for  x
      % expected type  posreal
  atan_lb_TCC1: OBLIGATION FORALL (x: real): x > 0 IMPLIES x >= 0;

  % Subtype TCC generated (at line 87, column 55) for  -x
      % expected type  posreal
  atan_lb_TCC2: OBLIGATION
    FORALL (x: real): NOT x = 0 AND NOT x > 0 IMPLIES -x >= 0 AND -x > 0;


body:
  exp_term: THEORY
  BEGIN

    IMPORTING reals@factorial

    a:   VAR real
    n0a: VAR nzreal
    n,m:   VAR nat
    i:   VAR int
    epsilon: VAR posreal
    f:   VAR [nat->real]

    exp_term(a)(n):real = IF n = 0 THEN 1 ELSE a^n/factorial(n) ENDIF

    exp_term_power: LEMMA a /= 0 IMPLIES
                                   abs(exp_term(a)(m*n)) <= abs(exp_term(a)(n))^m
    exp_term_decr:  LEMMA a /= 0 AND abs(a) < n+1 IMPLIES
                                   abs(exp_term(a)(n+1)) < abs(exp_term(a)(n))

    tends_to_0?(f):bool = FORALL epsilon: EXISTS n:
                                  FORALL i: i >= n IMPLIES abs(f(i)) < epsilon

    exp_tends_to_0: LEMMA tends_to_0?(exp_term(n0a))

  END exp_term

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 13, column 47) for  n
      % expected type  {i: int | a /= 0 OR i >= 0}
  exp_term_TCC1: OBLIGATION
    FORALL (a: real, n: nat): NOT n = 0 IMPLIES a /= 0 OR n >= 0;

  % Subtype TCC generated (at line 16, column 78) for  m
      % expected type  {i: int | abs(exp_term(a)(n)) /= 0 OR i >= 0}
  exp_term_power_TCC1: OBLIGATION
    FORALL (a: real, m, n: nat):
      a /= 0 IMPLIES abs(exp_term(a)(n)) /= 0 OR m >= 0;

  % Subtype TCC generated (at line 21, column 63) for  i
      % expected type  nat
  tends_to_0?_TCC1: OBLIGATION FORALL (n, i): i >= n IMPLIES i >= 0;


body:
  trig_approx: THEORY
  %-----------------------------------------------------------------------------
  %      trig_approx
  %      -----------
  %          - taylor series approximations to trig functions:
  %               sin_approx(a,n): sum first n terms of taylor expansion of sin
  %               cos_approx(a,n): sum first n terms of taylor expansion of cos
  %          - defines upper and lower bounds on trig functions:
  %
  %       Version 2 Foundational (DRL) 4/4/05
  %  
  %  CHANGES
  %    - Redefined sin_lb,sin_ub,cos_lb,cos_ub,tan_lb,tan_ub to make it 
  %      suitable for interval theory.
  %    - Removed lemmas SIN,COS,TAN. Use sin_bound_0_pi, cos_bound_npi2_pi2,
  %      tan_bound_0_pi2. Cesar Munoz (Nov 28 2003).
  %    - Added Hanne Gottliebsen's proofs for sin_bound_npi_0 and 
  %      cos_bound_npi_pi.
  %      Cesar Munoz (Feb 6 2004). 
  %    - Tan approximations moved to tan_approx due to circularity problems with
  %      trig_ineq. Cesar Munoz (Feb 6 2004)
  %    - The theory has been completely revisited by David Lester (4/4/05)
  %
  %-----------------------------------------------------------------------------

    BEGIN

    IMPORTING  sincos, exp_term,
               reals@factorial, 
               trig_ineq, reals@sigma_nat, 
               reals@real_fun_ops, reals@real_fun_preds

    m,n:  VAR nat
    pm:   VAR posnat
    a:    VAR real
    px:   VAR posreal
    n0x:  VAR nzreal
    nnx:  VAR nnreal

    AUTO_REWRITE+ sigma_0_neg

    sin_term(a)(n): real = (-1)^n*a^(2*n+1)/factorial(2*n+1)

    sin_term_next       : LEMMA sin_term(a)(n+1) =
                                sin_term(a)(n) * -1 * a*a / ((2*n+3)*(2*n+2))

    sin_term_neg        : LEMMA sin_term(-a)(n) = -sin_term(a)(n)

    sin_terms_alternate : LEMMA 0 /= a IMPLIES (sin_term(a)(n+1) < 0 IFF
                                                  sin_term(a)(n) > 0)

    sin_term_nonzero    : LEMMA sin_term(a)(n) /= 0 IFF a /= 0
    sin_term_zero       : LEMMA sin_term(a)(n)  = 0 IFF a  = 0
    sin_term_gt0        : LEMMA sin_term(a)(n)  > 0 IFF
                             ((even?(n) AND a > 0) OR (odd?(n) AND a < 0))
    sin_term_lt0        : LEMMA sin_term(a)(n)  < 0 IFF
                             ((even?(n) AND a < 0) OR (odd?(n) AND a > 0))

    sin_tends_to_0      : LEMMA tends_to_0?(sin_term(a))

    cos_term(a)(n): real = IF n=0 THEN 1 ELSE (-1)^n*a^(2*n)/factorial(2*n) ENDIF

    cos_term_next       : LEMMA cos_term(a)(n+1) =
                                cos_term(a)(n) * -1 * a*a / ((2*n+2)*(2*n+1))

    cos_term_neg        : LEMMA cos_term(-a)(n) = cos_term(a)(n)

    cos_terms_alternate : LEMMA 0 /= a IMPLIES (cos_term(a)(n+1) < 0 IFF
                                                  cos_term(a)(n) > 0)

    cos_term_nonzero    : LEMMA cos_term(a)(n) /= 0 IFF (n  = 0   OR  a /= 0)
    cos_term_zero       : LEMMA cos_term(a)(n)  = 0 IFF (n /= 0   AND a  = 0)
    cos_term_gt0        : LEMMA cos_term(a)(n)  > 0 IFF
                                     (even?(n) AND (a /= 0 OR n = 0))
    cos_term_lt0        : LEMMA cos_term(a)(n)  < 0 IFF (odd?(n) AND a /= 0)

    cos_tends_to_0      : LEMMA tends_to_0?(cos_term(n0x))

  %   sin_term_deriv: LEMMA derivable[real](LAMBDA a: sin_term(a)(n)) AND
  %       deriv[real](LAMBDA a: sin_term(a)(n)) = (LAMBDA a: cos_term(a)(n))

  %   cos_term_deriv: LEMMA derivable[real](LAMBDA a: cos_term(a)(n)) AND
  %       deriv[real](LAMBDA a: cos_term(a)(n)) =
  %                       (LAMBDA a: IF n = 0 THEN 0 ELSE -sin_term(a)(n-1) ENDIF)

    sin_approx(a,n):real = sigma(0,n,sin_term(a))

    sin_approx_a0:     LEMMA sin_approx(0,n) = 0

    sin_approx_neg:    LEMMA sin_approx(-a,n) = -sin_approx(a,n) 

    sin_approx_next:   LEMMA sin_approx(a,n+2) - sin_approx(a,n) = 
                              sin_term(a)(n+1) * (1 - a*a/((2*n+5)*(2*n+4)))

    sin_approx_eq:     LEMMA a*a = (2*n+5)*(2*n+4) IMPLIES
                              sin_approx(a,n+2) = sin_approx(a,n)

    sin_approx_sin:    LEMMA abs(sin(a)-sin_approx(a,n)) <= abs(sin_term(a)(n+1))

    cos_approx(a,n):real = sigma(0,n,cos_term(a))

    cos_approx_a0:     LEMMA cos_approx(0,n) = 1

    cos_approx_neg:    LEMMA cos_approx(-a,n) = cos_approx(a,n) 

    cos_approx_cos:    LEMMA abs(cos(a)-cos_approx(a,n)) <= abs(cos_term(a)(n+1))

    cos_approx_next:   LEMMA cos_approx(a,n+2) - cos_approx(a,n) = 
                              cos_term(a)(n+1) * (1 - a*a/((2*n+4)*(2*n+3)))

    cos_approx_eq:     LEMMA a*a = (2*n+4)*(2*n+3) IMPLIES
                              cos_approx(a,n+2) = cos_approx(a,n)

  %   sin_approx_deriv: LEMMA derivable[real](LAMBDA a: sin_approx(a,n)) AND
  %                     deriv[real](LAMBDA a: sin_approx(a,n))
  %                                                  = (LAMBDA a: cos_approx(a,n))

  %   cos_approx_deriv: LEMMA derivable[real](LAMBDA a: cos_approx(a,n)) AND
  %                     deriv[real](LAMBDA a: cos_approx(a,n)) =
  %                       (LAMBDA a: IF n = 0 THEN 0 ELSE -sin_approx(a,n-1) ENDIF)

    sin_ub(a,n):real = IF a < 0 THEN sin_approx(a,2*n+1)
                                ELSE sin_approx(a,2*n)   ENDIF
    sin_lb(a,n):real = IF a < 0 THEN sin_approx(a,2*n)
                                ELSE sin_approx(a,2*n+1) ENDIF

    sin_lb_neg: LEMMA sin_lb(-a,n) = -sin_ub(a,n)
    sin_ub_neg: LEMMA sin_ub(-a,n) = -sin_lb(a,n)

    sin_lb_a0 : LEMMA sin_lb(0,n) = 0
    sin_ub_a0 : LEMMA sin_ub(0,n) = 0

    sin_lb_ub : LEMMA sin_lb(n0x,n) < sin_ub(n0x,n)

    sin_lb_inc: LEMMA px*px < (4*n+7)*(4*n+6) => sin_lb(px,n) < sin_lb(px,n+pm)
    sin_ub_dec: LEMMA px*px < (4*n+5)*(4*n+4) => sin_ub(px,n+pm) < sin_ub(px,n)

    sin_lb_lt : LEMMA px*px < (4*n+7)*(4*n+6) => sin_lb(px,n) < sin(px)
    sin_ub_lt : LEMMA px*px < (4*n+5)*(4*n+4) => sin(px) < sin_ub(px,n)

    sin_lb_gt : LEMMA px*px > (4*n+7)*(4*n+6) => sin_lb(px,n) < -1
    sin_ub_gt : LEMMA px*px > (4*n+5)*(4*n+4) => sin_ub(px,n) >  1

    sin_lb     : LEMMA sin_lb(n0x,n) < sin(n0x)
    sin_ub     : LEMMA sin(n0x) < sin_ub(n0x,n)
    sin_bounds : LEMMA sin_lb(a,n) <= sin(a) AND sin(a) <= sin_ub(a,n)

    sin_lb_gt0: LEMMA px*px < 6 => sin_lb(px,n) > 0

    cos_ub(a,n):real = cos_approx(a,2*n)
    cos_lb(a,n):real = cos_approx(a,2*n+1)

    cos_lb_neg: LEMMA cos_lb(-a,n) = cos_lb(a,n)
    cos_ub_neg: LEMMA cos_ub(-a,n) = cos_ub(a,n)

    cos_lb_a0 : LEMMA cos_lb(0,n) = 1
    cos_ub_a0 : LEMMA cos_ub(0,n) = 1

    cos_lb_ub: LEMMA cos_lb(n0x,n) < cos_ub(n0x,n)

    cos_lb_inc: LEMMA n0x*n0x<(4*n+6)*(4*n+5) => cos_lb(n0x,n) < cos_lb(n0x,n+pm)
    cos_ub_dec: LEMMA n0x*n0x<(4*n+4)*(4*n+3) => cos_ub(n0x,n+pm) < cos_ub(n0x,n)

    cos_lb_lt:  LEMMA n0x*n0x < (4*n+6)*(4*n+5) => cos_lb(n0x,n) < cos(n0x)
    cos_ub_lt:  LEMMA n0x*n0x < (4*n+4)*(4*n+3) => cos(n0x) < cos_ub(n0x,n)

    cos_lb_gt:  LEMMA n0x*n0x > (4*n+6)*(4*n+5)        => cos_lb(n0x,n) < -1
    cos_ub_gt:  LEMMA n0x*n0x > (4*n+4)*(4*n+3) & n>=1 => cos_ub(n0x,n) >  1

    cos_lb:     LEMMA cos_lb(n0x,n) < cos(n0x)
    cos_ub:     LEMMA cos(n0x) < cos_ub(n0x,pm)

    cos_bounds:  LEMMA cos_lb(a,n) <= cos(a) AND cos(a) <= cos_ub(a,n)

  %   sin_lb_deriv: LEMMA derivable[nnreal](LAMBDA nnx: sin_lb(nnx,n)) AND
  %        deriv[nnreal](LAMBDA nnx: sin_lb(nnx,n)) = (LAMBDA nnx: cos_lb(nnx,n))

  %   sin_ub_deriv: LEMMA derivable[nnreal](LAMBDA nnx: sin_ub(nnx,n)) AND
  %        deriv[nnreal](LAMBDA nnx: sin_ub(nnx,n)) = (LAMBDA nnx: cos_ub(nnx,n))

  %   cos_lb_deriv: LEMMA derivable[real](LAMBDA a: cos_lb(a,n)) AND
  %        deriv[real](LAMBDA a: cos_lb(a,n))
  %          = (LAMBDA a: IF a < 0 THEN -sin_lb(a,n) ELSE -sin_ub(a,n) ENDIF)

  %   cos_ub_deriv: LEMMA derivable[real](LAMBDA a: cos_ub(a,n)) AND
  %        deriv[real](LAMBDA a: cos_ub(a,n))
  %          = (LAMBDA a: IF n = 0 THEN 0 ELSIF
  %                         a < 0 THEN -sin_ub(a,n-1) ELSE -sin_lb(a,n-1) ENDIF)

    cos_lb_nn_strict_decreasing: AXIOM 
              strict_decreasing?(LAMBDA (x:{x:nnreal| x <=  pi}): cos_lb(x,n))

    cos_lb_np_strict_increasing: LEMMA 
              strict_increasing?(LAMBDA (x:{x:npreal| x >= -pi}): cos_lb(x,n))

  %
  % ---- Added 1/8/2008
  %

     sin_px: LEMMA 1/500 > px => sin(px) > px*(1-1/1500000)

    % Approximation to guarantee cos_lb > 0

    IMPORTING atan_approx

    Cos_pos_n : MACRO posnat = 5 

    cos_term_pi_lb: LEMMA n >= Cos_pos_n IMPLIES
                          cos_term(pi_lbn(n)/2)(2*n+2) < cos(pi_lbn(n)/2)

    cos_lb_pi2_eps: LEMMA px <= pi/2 AND
                          abs(cos_term(pi/2-px)(2*n+2)) < sin(px) =>
                          cos_lb(pi/2-px,n) > 0

    cos_lb_pi2_pos0 : LEMMA n=0 => NOT cos_lb(pi_lbn(n)/2,n) > 0

    cos_lb_pi2_pos1 : LEMMA n=1 => NOT cos_lb(pi_lbn(n)/2,n) > 0

    cos_lb_pi2_pos2 : LEMMA n=2 => NOT cos_lb(pi_lbn(n)/2,n) > 0

    cos_lb_pi2_pos : LEMMA
      n >= Cos_pos_n IMPLIES
      cos_lb(pi_lbn(n)/2,n) > 0



    END trig_approx

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 42, column 35) for  (2 * n + 1)
      % expected type  {i: int | a /= 0 OR i >= 0}
  sin_term_TCC1: OBLIGATION
    FORALL (a: real, n: nat): a /= 0 OR (2 * n + 1) >= 0;

  % Subtype TCC generated (at line 61, column 54) for  (2 * n)
      % expected type  {i: int | a /= 0 OR i >= 0}
  cos_term_TCC1: OBLIGATION
    FORALL (a: real, n: nat): NOT n = 0 IMPLIES a /= 0 OR (2 * n) >= 0;

  % Subtype TCC generated (at line 86, column 33) for  n
      % expected type  T_high[nat]
  sin_approx_TCC1: OBLIGATION
    FORALL (n: nat): n >= 0 OR (EXISTS (j: nat): n <= j);


body:
  trig_degree : THEORY
  %-----------------------------------------------------------------------------
  %      trig_degree
  %      -----------
  %         - trig functions that take arguments in degrees: sind, cosd
  %         - defines conversions toRad, toDeg
  %
  %  CHANGES
  %     - SIN_pos and COS_pos renamed sind_bound and cosd_bound
  %-----------------------------------------------------------------------------
  BEGIN
    IMPORTING trig_basic,trig_approx,trig_ineq

    a : VAR real
    n : VAR posnat

    toRad(a)      : real = a*pi/180

    toDeg(a)      : real = a*180/pi

    rad_deg       : LEMMA toRad(toDeg(a)) = a

    deg_rad       : LEMMA toDeg(toRad(a)) = a

    sind(a)       : real = sin(toRad(a))

    cosd(a)       : real = cos(toRad(a))

    tand(a:real|Tan?(toRad(a))) : real = tan(toRad(a))

    sq_sin_cos_d_one : LEMMA  sq(sind(a)) + sq(cosd(a)) = 1

    sind_bounds : LEMMA 0 <= a AND a <= 90 IMPLIES
                        sind(a) >= sin_lb(a*pi_lb/180,n)

    cosd_bounds : LEMMA  0 <= a AND a <= 90 IMPLIES
                        cosd(a) <= cos_ub(a*pi_lb/180,n) 

  END trig_degree

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 29, column 43) for  toRad(a)
      % expected type  (Tan?)
  tand_TCC1: OBLIGATION FORALL (a: real | Tan?(toRad(a))): Tan?(toRad(a));


body:
  law_cosines: THEORY
  BEGIN

  %   Version 1.2 27/10/03  Foundational Version David Lester

  %                                   (x2,y2)
  %                                      .
  %                                     / \
  %                                   /    \
  %                                 /       \
  %                               /          \
  %                      b      /             \
  %                           /                \    c
  %                         /                   \
  %                       /                      \
  %                     /                         \
  %                   /                            \
  %                 /                           ac  \
  %               /                                  \
  %               ------------------------------------ 
  %           (x0,y0)               a               (x1,y1)

    IMPORTING trig_basic %, atan2

    x0,x1,x2,y0,y1,y2,ac : VAR real
    pz                   : VAR posreal

    sq_dist(x0,y0,x1,y1) : nonneg_real = sq(x0-x1)+sq(y0-y1)

    dist(x0,y0,x1,y1)    : nonneg_real = sqrt(sq_dist(x0,y0,x1,y1))

    distance_refl : LEMMA  dist(x0,y0,x0,y0) = 0

    distance_symm : LEMMA  dist(x0,y0,x1,y1) = dist(x1,y1,x0,y0)

    distance_trans: LEMMA  dist(x0,y0,x1,y1) = dist(x0+x2,y0+y2,x1+x2,y1+y2)

    distance_scale: LEMMA  pz*dist(x0,y0,x1,y1) = dist(pz*x0,pz*y0,pz*x1,pz*y1)

    distance_rot:   LEMMA  dist(x0,y0,x1,y1)
                             = dist(cos(ac)*x0-sin(ac)*y0, cos(ac)*y0+sin(ac)*x0,
                                    cos(ac)*x1-sin(ac)*y1, cos(ac)*y1+sin(ac)*x1)

    dot_product   : AXIOM
                       LET a = dist(x1,y1,x0,y0),
                           b = dist(x2,y2,x0,y0),
                           c = dist(x2,y2,x1,y1) IN
                       EXISTS (ac) : 
                           a*c*cos(ac) = ((x0-x1)*(x2-x1) + (y0-y1)*(y2-y1))

    Law_Cosines   : LEMMA
                       LET a = dist(x1,y1,x0,y0),
                           b = dist(x2,y2,x0,y0),
                           c = dist(x2,y2,x1,y1) IN
                           a*c*cos(ac) = ((x0-x1)*(x2-x1) + (y0-y1)*(y2-y1))
                       IMPLIES
                             sq(b) = sq(c) + sq(a) - 2*a*c*cos(ac)
                         
    triangle      : AXIOM  dist(x0,y0,x1,y1) <= 
                                dist(x2,y2,x1,y1) + dist(x2,y2,x0,y0)
   
  END law_cosines


body:
  tan_approx : THEORY
  %-----------------------------------------------------------------------------
  %      tan_approx
  %      -----------
  %        tangent approximations
  %        Cesar Munoz (Feb 6 2004)
  %  
  %-----------------------------------------------------------------------------
  BEGIN
    IMPORTING trig_approx

    n   : VAR nat
    a,b : VAR real

  % Approximations tan

    tan_lb_ub(a:real,(n|cos_ub(a,n) /= 0)): real = sin_lb(a,n)/cos_ub(a,n)

    tan_ub_lb(a:real,(n|cos_lb(a,n) /= 0)): real = sin_ub(a,n)/cos_lb(a,n)

    tan_lb_lb(a:real,(n|cos_lb(a,n) /= 0)): real = sin_lb(a,n)/cos_lb(a,n)

    tan_ub_ub(a:real,(n|cos_ub(a,n) /= 0)): real = sin_ub(a,n)/cos_ub(a,n)

    tan_lb_ub_neg : LEMMA
      cos_ub(a,n) /= 0 IMPLIES
      tan_lb_ub(-a,n) = -tan_ub_ub(a,n)
   
    tan_ub_lb_neg : LEMMA
      cos_lb(a,n) /= 0 IMPLIES
      tan_ub_lb(-a,n) = -tan_lb_lb(a,n)
   
    tan_lb_lb_neg : LEMMA
      cos_lb(a,n) /= 0 IMPLIES
      tan_lb_lb(-a,n) = -tan_ub_lb(a,n)

    tan_ub_ub_neg : LEMMA
      cos_ub(a,n) /= 0 IMPLIES
      tan_ub_ub(-a,n) = -tan_lb_ub(a,n)

    tan_bounds_0_pi2 : LEMMA
      0 <= a AND a < pi/2 AND cos_lb(a,n) > 0 IMPLIES
      tan_lb_ub(a,n) <= tan(a) AND
      tan(a) <= tan_ub_lb(a,n)
   
    tan_bounds_npi2_0 : LEMMA
      -pi/2 < a AND a <= 0 AND cos_lb(a,n) > 0 IMPLIES
      tan_lb_lb(a,n) <= tan(a) AND
      tan(a) <= tan_ub_ub(a,n)

    tan_bounds_pi2_pi : LEMMA
      pi/2 < a AND a <= pi AND cos_ub(a,n) < 0 IMPLIES
      tan_ub_ub(a,n) <= tan(a) AND
      tan(a) <= tan_lb_lb(a,n)

    tan_bounds_npi_npi2 : LEMMA
      -pi <= a AND a < -pi/2 AND cos_ub(a,n) < 0 IMPLIES
      tan_ub_lb(a,n) <= tan(a) AND
      tan(a) <= tan_lb_ub(a,n)

  END tan_approx

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 17, column 61) for  cos_ub(a, n)
      % expected type  nznum
  tan_lb_ub_TCC1: OBLIGATION
    FORALL (a: real, (n: nat | cos_ub(a, n) /= 0)): cos_ub(a, n) /= 0;

  % Subtype TCC generated (at line 19, column 61) for  cos_lb(a, n)
      % expected type  nznum
  tan_ub_lb_TCC1: OBLIGATION
    FORALL (a: real, (n: nat | cos_lb(a, n) /= 0)): cos_lb(a, n) /= 0;

  % Subtype TCC generated (at line 27, column 17) for  n
      % expected type  {n | cos_ub(-a, n) /= 0}
  tan_lb_ub_neg_TCC1: OBLIGATION
    FORALL (a: real, n: nat): cos_ub(a, n) /= 0 IMPLIES cos_ub(-a, n) /= 0;

  % Subtype TCC generated (at line 31, column 17) for  n
      % expected type  {n | cos_lb(-a, n) /= 0}
  tan_ub_lb_neg_TCC1: OBLIGATION
    FORALL (a: real, n: nat): cos_lb(a, n) /= 0 IMPLIES cos_lb(-a, n) /= 0;

  % Subtype TCC generated (at line 43, column 16) for  n
      % expected type  {n | cos_ub(a, n) /= 0}
  tan_bounds_0_pi2_TCC1: OBLIGATION
    FORALL (a: real, n: nat):
      cos_lb(a, n) > 0 AND a < pi / 2 AND 0 <= a IMPLIES cos_ub(a, n) /= 0;

  % Subtype TCC generated (at line 43, column 26) for  a
      % expected type  (Tan?)
  tan_bounds_0_pi2_TCC2: OBLIGATION
    FORALL (a: real, n: nat):
      cos_lb(a, n) > 0 AND a < pi / 2 AND 0 <= a IMPLIES Tan?(a);

  % Subtype TCC generated (at line 44, column 26) for  n
      % expected type  {n | cos_lb(a, n) /= 0}
  tan_bounds_0_pi2_TCC3: OBLIGATION
    FORALL (a: real, n: nat):
      cos_lb(a, n) > 0 AND
       a < pi / 2 AND 0 <= a AND tan_lb_ub(a, n) <= tan(a)
       IMPLIES cos_lb(a, n) /= 0;

  % Subtype TCC generated (at line 48, column 16) for  n
      % expected type  {n | cos_lb(a, n) /= 0}
  tan_bounds_npi2_0_TCC1: OBLIGATION
    FORALL (a: real, n: nat):
      cos_lb(a, n) > 0 AND a <= 0 AND -pi / 2 < a IMPLIES cos_lb(a, n) /= 0;

  % Subtype TCC generated (at line 48, column 26) for  a
      % expected type  (Tan?)
  tan_bounds_npi2_0_TCC2: OBLIGATION
    FORALL (a: real, n: nat):
      cos_lb(a, n) > 0 AND a <= 0 AND -pi / 2 < a IMPLIES Tan?(a);

  % Subtype TCC generated (at line 49, column 26) for  n
      % expected type  {n | cos_ub(a, n) /= 0}
  tan_bounds_npi2_0_TCC3: OBLIGATION
    FORALL (a: real, n: nat):
      cos_lb(a, n) > 0 AND
       a <= 0 AND -pi / 2 < a AND tan_lb_lb(a, n) <= tan(a)
       IMPLIES cos_ub(a, n) /= 0;

  % Subtype TCC generated (at line 53, column 16) for  n
      % expected type  {n | cos_ub(a, n) /= 0}
  tan_bounds_pi2_pi_TCC1: OBLIGATION
    FORALL (a: real, n: nat):
      cos_ub(a, n) < 0 AND a <= pi AND pi / 2 < a IMPLIES cos_ub(a, n) /= 0;

  % Subtype TCC generated (at line 53, column 26) for  a
      % expected type  (Tan?)
  tan_bounds_pi2_pi_TCC2: OBLIGATION
    FORALL (a: real, n: nat):
      cos_ub(a, n) < 0 AND a <= pi AND pi / 2 < a IMPLIES Tan?(a);

  % Subtype TCC generated (at line 54, column 26) for  n
      % expected type  {n | cos_lb(a, n) /= 0}
  tan_bounds_pi2_pi_TCC3: OBLIGATION
    FORALL (a: real, n: nat):
      cos_ub(a, n) < 0 AND
       a <= pi AND pi / 2 < a AND tan_ub_ub(a, n) <= tan(a)
       IMPLIES cos_lb(a, n) /= 0;

  % Subtype TCC generated (at line 58, column 16) for  n
      % expected type  {n | cos_lb(a, n) /= 0}
  tan_bounds_npi_npi2_TCC1: OBLIGATION
    FORALL (a: real, n: nat):
      cos_ub(a, n) < 0 AND a < -pi / 2 AND -pi <= a IMPLIES cos_lb(a, n) /= 0;

  % Subtype TCC generated (at line 58, column 26) for  a
      % expected type  (Tan?)
  tan_bounds_npi_npi2_TCC2: OBLIGATION
    FORALL (a: real, n: nat):
      cos_ub(a, n) < 0 AND a < -pi / 2 AND -pi <= a IMPLIES Tan?(a);

  % Subtype TCC generated (at line 59, column 26) for  n
      % expected type  {n | cos_ub(a, n) /= 0}
  tan_bounds_npi_npi2_TCC3: OBLIGATION
    FORALL (a: real, n: nat):
      cos_ub(a, n) < 0 AND
       a < -pi / 2 AND -pi <= a AND tan_ub_lb(a, n) <= tan(a)
       IMPLIES cos_ub(a, n) /= 0;


body:
  trig_extra : THEORY
  %-----------------------------------------------------------------------------
  %      trig_extra
  %      ----------
  %         - reduction theorems
  %         - sum and product identities
  %         - half-angle identities and zeros
  %         - triple angle formulas
  %-----------------------------------------------------------------------------
  BEGIN

     IMPORTING trig_basic, trig_values


    a,b             : VAR real

  % ------------------------- Reduction Theorems -------------------------

    sin_minus_2pi    : LEMMA sin(a - 2*pi) = sin(a)  
    cos_minus_2pi    : LEMMA cos(a - 2*pi) = cos(a) 
    tan_minus_2pi    : LEMMA cos(a) /= 0 IMPLIES tan(a - 2*pi) = tan(a) 

    sin_minus_3pi2   : LEMMA sin(a - 3*pi/2) =   cos(a)
    cos_minus_3pi2   : LEMMA cos(a - 3*pi/2) = - sin(a)
    tan_minus_3pi2   : LEMMA sin(a) /= 0 AND cos(a) /= 0 
                                IMPLIES tan(a - 3*pi/2) = - 1/tan(a)

    sin_minus_pi     : LEMMA sin(a - pi) = - sin(a)
    cos_minus_pi     : LEMMA cos(a - pi) = - cos(a)
    tan_minus_pi     : LEMMA cos(a) /= 0 IMPLIES tan(a - pi) =   tan(a)

    sin_minus_pi2    : LEMMA sin(a - pi/2) = - cos(a)
    cos_minus_pi2    : LEMMA cos(a - pi/2) =   sin(a)
    tan_minus_pi2    : LEMMA sin(a) /= 0 AND cos(a) /= 0 
                                IMPLIES tan(a - pi/2) = - 1/tan(a)

    sin_2pi_minus    : LEMMA sin(2*pi - a) = - sin(a)
    cos_2pi_minus    : LEMMA cos(2*pi - a) =   cos(a)
    tan_2pi_minus    : LEMMA sin(a) /= 0 AND cos(a) /= 0 
                                IMPLIES tan(2*pi - a) =   - tan(a)
                                 
    sin_3pi2_minus   : LEMMA sin(3*pi/2 - a) = - cos(a)
    cos_3pi2_minus   : LEMMA cos(3*pi/2 - a) = - sin(a)
    tan_3pi2_minus   : LEMMA sin(a) /= 0 AND cos(a) /= 0 
  	                             IMPLIES tan(3*pi/2 - a) =   1/tan(a)
                                 
    sin_pi_minus     : LEMMA sin(pi - a) =   sin(a)
    cos_pi_minus     : LEMMA cos(pi - a) = - cos(a)
    tan_pi_minus     : LEMMA cos(a) /= 0 IMPLIES tan(pi - a) = - tan(a)
                                 
    sin_pi2_minus    : LEMMA sin(pi/2 - a) = cos(a)
    cos_pi2_minus    : LEMMA cos(pi/2 - a) = sin(a)
    tan_pi2_minus    : LEMMA sin(a) /= 0 AND cos(a) /= 0 
                                IMPLIES tan(pi/2 - a) = 1/tan(a)

  % ------------------------- Sum and Product Formulas -------------------------

    sin_times_cos    : LEMMA sin(a)*cos(b) = (sin(a+b) + sin(a-b))/2
    cos_times_cos    : LEMMA cos(a)*cos(b) = (cos(a+b) + cos(a-b))/2
    sin_times_sin    : LEMMA sin(a)*sin(b) = (cos(a-b) - cos(a+b))/2

    sin_sum          : LEMMA sin(a) + sin(b) =   2 * sin((a+b)/2)*cos((a-b)/2)
    sin_diff         : LEMMA sin(a) - sin(b) =   2 * cos((a+b)/2)*sin((a-b)/2)
    cos_sum          : LEMMA cos(a) + cos(b) =   2 * cos((a+b)/2)*cos((a-b)/2)
    cos_diff         : LEMMA cos(a) - cos(b) = - 2 * sin((a+b)/2)*sin((a-b)/2)

    tan_diff         : LEMMA Tan?(a) AND Tan?(b) IMPLIES
                                tan(a) - tan(b) = sin(a-b)/(cos(a)*cos(b))

  % ------------------------- Squares of sin and cos -------------------------

    sq_sin           : LEMMA sq(sin(a)) = (1-cos(2*a))/2
    sq_cos           : LEMMA sq(cos(a)) = (1+cos(2*a))/2
    sin_half_zeroes  : LEMMA sin(a/2) = 0 IFF 1-cos(a) = 0
    cos_half_zeroes  : LEMMA cos(a/2) = 0 IFF 1+cos(a) = 0
    cos_half_zeroes2 : LEMMA cos(a/2) = 0 IMPLIES sin(a) = 0
    sq_tan           : LEMMA (1+cos(2*a)) /= 0 
                                  IMPLIES sq(tan(a)) = (1-cos(2*a))/(1+cos(2*a))

  % ------------------------- Half Angle Formulas -------------------------

    IMPORTING trig_ineq 

    sin_half  : LEMMA 
                  ( 0 <= a/2 AND a/2 <= pi IMPLIES
                    sin(a/2) = sqrt((1-cos(a))/2))  AND
                  ( pi <= a/2 AND a/2 <= 2*pi IMPLIES
                    sin(a/2) = -sqrt((1-cos(a))/2))

    cos_half  : LEMMA 
                  ( 0 <= a/2 AND a/2 <= pi/2 IMPLIES
                    cos(a/2) = sqrt((1+cos(a))/2))  AND
                  ( pi/2 <= a/2 AND a/2 <= 3*pi/2 IMPLIES
                    cos(a/2) = -sqrt((1+cos(a))/2)) AND 
                  ( 3*pi/2 <= a/2 AND a/2 <= 2*pi IMPLIES
                    cos(a/2) = sqrt((1+cos(a))/2)) 

    tan_half  : LEMMA
                  cos(a) /= -1 IMPLIES tan(a/2) = sin(a)/(1 + cos(a)) 

    tan_half2 : LEMMA
                  sin(a) /= 0 IMPLIES tan(a/2) = (1 - cos(a))/sin(a)

  % ---------------------- Triple Angle Formulas ----------------------

    sin_3a      : LEMMA sin(3*a) = 3 * sin(a) - 4 * expt(sin(a),3)
    cos_3a      : LEMMA cos(3*a) = 4 * expt(cos(a),3) - 3 * cos(a)

  % ---------------------- Base equations ---------------------

    sin_eq_sin  : LEMMA sin(a) = sin(b) <=> 
                     (EXISTS (k: int): (a = b + 2*k*pi) OR (a = pi - b + 2*k*pi)) 

    cos_eq_cos  : LEMMA cos(a) = cos(b) <=> 
                     (EXISTS (k: int): (a = b + 2*k*pi) OR (a = -b + 2*k*pi)) 

    tan_eq_tan  : LEMMA Tan?(a) AND Tan?(b) IMPLIES
                        ( tan(a) = tan(b) <=> (EXISTS (k: int): (a = b + k*pi)) )

    sin_cos_eq: LEMMA FORALL (a,b: {x:nnreal | x < 2*pi}): 
                                 sin(a) = sin(b) AND cos(a) = cos(b)
                                 IMPLIES a = b

    sin_eq_cos: LEMMA sin(a) = cos(a) IMPLIES (EXISTS (i:int): a = pi/4 + i*pi)

    tan_eq_1  : LEMMA Tan?(a) AND tan(a) = 1 IMPLIES (EXISTS (i:int): a = pi/4 + i*pi)


    i,j: VAR integer

    sin_eq_pm1  : LEMMA sin(a) = (-1)^i IFF (EXISTS j: a = (i+2*j)*pi + pi/2)
    cos_eq_pm1  : LEMMA cos(a) = (-1)^i IFF (EXISTS j: a = (i+2*j)*pi)


  % --------------------- Superposition ----------------------

    A,B: VAR real
    C: VAR nzreal
    x,y,del,W, alpha: VAR real

    sin_plus_cos: LEMMA sq(C) = sq(A) + sq(B) AND sin(del) = B/C
                          AND cos(del) = A/C  IMPLIES
                          A*sin(x) + B*cos(x) = C*sin(x+del)

    spc_tan_prep: LEMMA A /= 0 AND Tan?(del) AND tan(del) = B/A AND 
                        sq(C) = sq(A) + sq(B) IMPLIES
                           sq(sin(del)) = sq(B/C) AND sq(cos(del)) = sq(A/C)

    IMPORTING atan2

    sin_plus_cos_atan2: LEMMA
       x /= 0 OR y /= 0 IMPLIES
         x*sin(alpha) + y*cos(alpha) = sqrt(sq(x)+sq(y))*sin(alpha + atan2(x,y))


  %   sin_superpos: LEMMA A + B*cos(W) = C*cos(del) AND  % need to find f:
  %                           B*sin(W) = C*sin(del)      % del = f(A,B,C,W)
  %                       IMPLIES
  %                           A*sin(x) + B*sin(x+W) = C*sin(x+del)

     
  END trig_extra

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 21, column 51) for  a - 2 * pi
      % expected type  (Tan?)
  tan_minus_2pi_TCC1: OBLIGATION
    FORALL (a: real): cos(a) /= 0 IMPLIES Tan?(a - 2 * pi);

  % Subtype TCC generated (at line 21, column 67) for  a
      % expected type  (Tan?)
  tan_minus_2pi_TCC2: OBLIGATION
    FORALL (a: real): cos(a) /= 0 IMPLIES Tan?(a);

  % Subtype TCC generated (at line 26, column 42) for  a - 3 * pi / 2
      % expected type  (Tan?)
  tan_minus_3pi2_TCC1: OBLIGATION
    FORALL (a: real):
      cos(a) /= 0 AND sin(a) /= 0 IMPLIES Tan?(a - 3 * pi / 2);

  % Subtype TCC generated (at line 26, column 60) for  tan(a)
      % expected type  nznum
  tan_minus_3pi2_TCC2: OBLIGATION
    FORALL (a: real): cos(a) /= 0 AND sin(a) /= 0 IMPLIES tan(a) /= 0;

  % Subtype TCC generated (at line 30, column 51) for  a - pi
      % expected type  (Tan?)
  tan_minus_pi_TCC1: OBLIGATION
    FORALL (a: real): cos(a) /= 0 IMPLIES Tan?(a - pi);

  % Subtype TCC generated (at line 35, column 42) for  a - pi / 2
      % expected type  (Tan?)
  tan_minus_pi2_TCC1: OBLIGATION
    FORALL (a: real): cos(a) /= 0 AND sin(a) /= 0 IMPLIES Tan?(a - pi / 2);

  % Subtype TCC generated (at line 40, column 42) for  2 * pi - a
      % expected type  (Tan?)
  tan_2pi_minus_TCC1: OBLIGATION
    FORALL (a: real): cos(a) /= 0 AND sin(a) /= 0 IMPLIES Tan?(2 * pi - a);

  % Subtype TCC generated (at line 45, column 42) for  3 * pi / 2 - a
      % expected type  (Tan?)
  tan_3pi2_minus_TCC1: OBLIGATION
    FORALL (a: real):
      cos(a) /= 0 AND sin(a) /= 0 IMPLIES Tan?(3 * pi / 2 - a);

  % Subtype TCC generated (at line 49, column 51) for  pi - a
      % expected type  (Tan?)
  tan_pi_minus_TCC1: OBLIGATION
    FORALL (a: real): cos(a) /= 0 IMPLIES Tan?(pi - a);

  % Subtype TCC generated (at line 54, column 42) for  pi / 2 - a
      % expected type  (Tan?)
  tan_pi2_minus_TCC1: OBLIGATION
    FORALL (a: real): cos(a) /= 0 AND sin(a) /= 0 IMPLIES Tan?(pi / 2 - a);

  % Subtype TCC generated (at line 68, column 58) for  (cos(a) * cos(b))
      % expected type  nznum
  tan_diff_TCC1: OBLIGATION
    FORALL (a, b: real): Tan?(b) AND Tan?(a) IMPLIES (cos(a) * cos(b)) /= 0;

  % Subtype TCC generated (at line 78, column 47) for  a
      % expected type  (Tan?)
  sq_tan_TCC1: OBLIGATION
    FORALL (a: real): (1 + cos(2 * a)) /= 0 IMPLIES Tan?(a);

  % Subtype TCC generated (at line 86, column 34) for  (1 - cos(a)) / 2
      % expected type  nnx: nonneg_real
  sin_half_TCC1: OBLIGATION
    FORALL (a: real):
      a / 2 <= pi AND 0 <= a / 2 IMPLIES (1 - cos(a)) / 2 >= 0;

  % Subtype TCC generated (at line 88, column 35) for  (1 - cos(a)) / 2
      % expected type  nnx: nonneg_real
  sin_half_TCC2: OBLIGATION
    FORALL (a: real):
      (0 <= a / 2 AND a / 2 <= pi IMPLIES
        sin(a / 2) = sqrt((1 - cos(a)) / 2))
       AND a / 2 <= 2 * pi AND pi <= a / 2
       IMPLIES (1 - cos(a)) / 2 >= 0;

  % Subtype TCC generated (at line 92, column 34) for  (1 + cos(a)) / 2
      % expected type  nnx: nonneg_real
  cos_half_TCC1: OBLIGATION
    FORALL (a: real):
      a / 2 <= pi / 2 AND 0 <= a / 2 IMPLIES (1 + cos(a)) / 2 >= 0;

  % Subtype TCC generated (at line 94, column 35) for  (1 + cos(a)) / 2
      % expected type  nnx: nonneg_real
  cos_half_TCC2: OBLIGATION
    FORALL (a: real):
      (0 <= a / 2 AND a / 2 <= pi / 2 IMPLIES
        cos(a / 2) = sqrt((1 + cos(a)) / 2))
       AND a / 2 <= 3 * pi / 2 AND pi / 2 <= a / 2
       IMPLIES (1 + cos(a)) / 2 >= 0;

  % Subtype TCC generated (at line 96, column 34) for  (1 + cos(a)) / 2
      % expected type  nnx: nonneg_real
  cos_half_TCC3: OBLIGATION
    FORALL (a: real):
      (0 <= a / 2 AND a / 2 <= pi / 2 IMPLIES
        cos(a / 2) = sqrt((1 + cos(a)) / 2))
       AND
       (pi / 2 <= a / 2 AND a / 2 <= 3 * pi / 2 IMPLIES
         cos(a / 2) = -sqrt((1 + cos(a)) / 2))
        AND a / 2 <= 2 * pi AND 3 * pi / 2 <= a / 2
       IMPLIES (1 + cos(a)) / 2 >= 0;

  % Subtype TCC generated (at line 99, column 41) for  a / 2
      % expected type  (Tan?)
  tan_half_TCC1: OBLIGATION
    FORALL (a: real): cos(a) /= -1 IMPLIES Tan?(a / 2);

  % Subtype TCC generated (at line 99, column 56) for  (1 + cos(a))
      % expected type  nznum
  tan_half_TCC2: OBLIGATION
    FORALL (a: real): cos(a) /= -1 IMPLIES (1 + cos(a)) /= 0;

  % Subtype TCC generated (at line 102, column 40) for  a / 2
      % expected type  (Tan?)
  tan_half2_TCC1: OBLIGATION
    FORALL (a: real): sin(a) /= 0 IMPLIES Tan?(a / 2);

  % Subtype TCC generated (at line 153, column 75) for  y
      % expected type  {z: real | x = 0 => z /= 0}
  sin_plus_cos_atan2_TCC1: OBLIGATION
    FORALL (x, y: real): x /= 0 OR y /= 0 IMPLIES x = 0 => y /= 0;


body:
  trig: THEORY
  %------------------------------------------------------------------------
  %
  % A Pragmatic Nonfoundational Theory of Trigonometry
  %
  %       by Cesar Munoz
  %          Victor Carreno
  %          Ricky Butler
  %          Gilles Dowek
  %          Alfons Geser
  %          Ben Di Vito
  % 
  %      Version 1.0    3/27/01
  %
  %
  %------------------------------------------------------------------------

  BEGIN

     trig_basic_ax  : THEORY  = trig_basic
     trig_values_ax : THEORY = trig_values
     trig_ineq_ax   : THEORY = trig_ineq

  END trig

addendum:
  %%% ================ Addendum: generated declarations ================

  trig_basic_ax.trig_phase_TCC1: OBLIGATION 0 < 2 * trig_basic_ax.pi;

  trig_basic_ax.sin_range_ax: AXIOM
    -1 <= trig_basic_ax.sin(a) AND trig_basic_ax.sin(a) <= 1

  trig_basic_ax.cos_range_ax: AXIOM
    -1 <= trig_basic_ax.cos(a) AND trig_basic_ax.cos(a) <= 1

  trig_basic_ax.sin_range: OBLIGATION
    FORALL (a): -1 <= trig_basic_ax.sin(a) AND trig_basic_ax.sin(a) <= 1;

  trig_basic_ax.cos_range: OBLIGATION
    FORALL (a): -1 <= trig_basic_ax.cos(a) AND trig_basic_ax.cos(a) <= 1;

  trig_basic_ax.tan_TCC1: OBLIGATION
    FORALL (a: (trig_basic_ax.Tan?)): trig_basic_ax.cos(a) /= 0;

  trig_basic_ax.sin2_cos2: AXIOM
    sq(trig_basic_ax.sin(a)) + sq(trig_basic_ax.cos(a)) = 1

  trig_basic_ax.cos2: LEMMA
    sq(trig_basic_ax.cos(a)) = 1 - sq(trig_basic_ax.sin(a))

  trig_basic_ax.sin2: LEMMA
    sq(trig_basic_ax.sin(a)) = 1 - sq(trig_basic_ax.cos(a))

  trig_basic_ax.cos_0: AXIOM trig_basic_ax.cos(0) = 1

  trig_basic_ax.sin_0: LEMMA trig_basic_ax.sin(0) = 0

  trig_basic_ax.sin_pi2: AXIOM trig_basic_ax.sin(trig_basic_ax.pi / 2) = 1

  trig_basic_ax.cos_pi2: LEMMA trig_basic_ax.cos(trig_basic_ax.pi / 2) = 0

  trig_basic_ax.tan_0_TCC1: OBLIGATION trig_basic_ax.Tan?(0);

  trig_basic_ax.tan_0: LEMMA trig_basic_ax.tan(0) = 0

  trig_basic_ax.sin_neg: AXIOM trig_basic_ax.sin(-a) = -trig_basic_ax.sin(a)

  trig_basic_ax.cos_neg: AXIOM trig_basic_ax.cos(-a) = trig_basic_ax.cos(a)

  trig_basic_ax.tan_neg_TCC1: OBLIGATION
    FORALL (a: (trig_basic_ax.Tan?)): trig_basic_ax.Tan?(-a);

  trig_basic_ax.tan_neg: LEMMA
    FORALL (a: (trig_basic_ax.Tan?)):
      trig_basic_ax.tan(-a) = -trig_basic_ax.tan(a)

  trig_basic_ax.cos_sin: AXIOM
    trig_basic_ax.cos(a) = trig_basic_ax.sin(a + trig_basic_ax.pi / 2)

  trig_basic_ax.sin_cos: LEMMA
    trig_basic_ax.sin(a) = -trig_basic_ax.cos(a + trig_basic_ax.pi / 2)

  trig_basic_ax.sin_shift: LEMMA
    trig_basic_ax.sin(trig_basic_ax.pi / 2 - a) = trig_basic_ax.cos(a)

  trig_basic_ax.cos_shift: LEMMA
    trig_basic_ax.cos(trig_basic_ax.pi / 2 - a) = trig_basic_ax.sin(a)

  trig_basic_ax.neg_cos: LEMMA
    -trig_basic_ax.cos(a) = trig_basic_ax.cos(a + trig_basic_ax.pi)

  trig_basic_ax.neg_sin: LEMMA
    -trig_basic_ax.sin(a) = trig_basic_ax.sin(a + trig_basic_ax.pi)

  trig_basic_ax.sin_pi: AXIOM trig_basic_ax.sin(trig_basic_ax.pi) = 0

  trig_basic_ax.cos_pi: AXIOM trig_basic_ax.cos(trig_basic_ax.pi) = -1

  trig_basic_ax.tan_pi_TCC1: OBLIGATION trig_basic_ax.Tan?(trig_basic_ax.pi);

  trig_basic_ax.tan_pi: LEMMA trig_basic_ax.tan(trig_basic_ax.pi) = 0

  trig_basic_ax.sin_3pi2: LEMMA
    trig_basic_ax.sin(3 * trig_basic_ax.pi / 2) = -1

  trig_basic_ax.cos_3pi2: LEMMA
    trig_basic_ax.cos(3 * trig_basic_ax.pi / 2) = 0

  trig_basic_ax.sin_2pi: AXIOM trig_basic_ax.sin(2 * trig_basic_ax.pi) = 0

  trig_basic_ax.cos_2pi: AXIOM trig_basic_ax.cos(2 * trig_basic_ax.pi) = 1

  trig_basic_ax.tan_2pi_TCC1: OBLIGATION
    trig_basic_ax.Tan?(2 * trig_basic_ax.pi);

  trig_basic_ax.tan_2pi: LEMMA trig_basic_ax.tan(2 * trig_basic_ax.pi) = 0

  trig_basic_ax.sin_plus: AXIOM
    trig_basic_ax.sin(a + b) =
     trig_basic_ax.sin(a) * trig_basic_ax.cos(b) +
      trig_basic_ax.cos(a) * trig_basic_ax.sin(b)

  trig_basic_ax.sin_minus: LEMMA
    trig_basic_ax.sin(a - b) =
     trig_basic_ax.sin(a) * trig_basic_ax.cos(b) -
      trig_basic_ax.sin(b) * trig_basic_ax.cos(a)

  trig_basic_ax.cos_plus: LEMMA
    trig_basic_ax.cos(a + b) =
     trig_basic_ax.cos(a) * trig_basic_ax.cos(b) -
      trig_basic_ax.sin(a) * trig_basic_ax.sin(b)

  trig_basic_ax.cos_minus: LEMMA
    trig_basic_ax.cos(a - b) =
     trig_basic_ax.cos(a) * trig_basic_ax.cos(b) +
      trig_basic_ax.sin(a) * trig_basic_ax.sin(b)

  trig_basic_ax.sin_pi_minus: LEMMA
    trig_basic_ax.sin(trig_basic_ax.pi - a) = trig_basic_ax.sin(a)

  trig_basic_ax.cos_pi_minus: LEMMA
    trig_basic_ax.cos(trig_basic_ax.pi - a) = -trig_basic_ax.cos(a)

  trig_basic_ax.tan_plus_TCC1: OBLIGATION
    FORALL (a, b: real):
      trig_basic_ax.tan(a) * trig_basic_ax.tan(b) /= 1 AND
       trig_basic_ax.Tan?(a + b) AND
        trig_basic_ax.Tan?(b) AND trig_basic_ax.Tan?(a)
       IMPLIES (1 - trig_basic_ax.tan(a) * trig_basic_ax.tan(b)) /= 0;

  trig_basic_ax.tan_plus: LEMMA
    trig_basic_ax.Tan?(a) AND
     trig_basic_ax.Tan?(b) AND
      trig_basic_ax.Tan?(a + b) AND
       trig_basic_ax.tan(a) * trig_basic_ax.tan(b) /= 1
     IMPLIES
     trig_basic_ax.tan(a + b) =
      (trig_basic_ax.tan(a) + trig_basic_ax.tan(b)) /
       (1 - trig_basic_ax.tan(a) * trig_basic_ax.tan(b))

  trig_basic_ax.tan_minus_TCC1: OBLIGATION
    FORALL (a, b: real):
      trig_basic_ax.tan(a) * trig_basic_ax.tan(b) /= -1 AND
       trig_basic_ax.Tan?(a - b) AND
        trig_basic_ax.Tan?(b) AND trig_basic_ax.Tan?(a)
       IMPLIES (1 + trig_basic_ax.tan(a) * trig_basic_ax.tan(b)) /= 0;

  trig_basic_ax.tan_minus: LEMMA
    trig_basic_ax.Tan?(a) AND
     trig_basic_ax.Tan?(b) AND
      trig_basic_ax.Tan?(a - b) AND
       trig_basic_ax.tan(a) * trig_basic_ax.tan(b) /= -1
     IMPLIES
     trig_basic_ax.tan(a - b) =
      (trig_basic_ax.tan(a) - trig_basic_ax.tan(b)) /
       (1 + trig_basic_ax.tan(a) * trig_basic_ax.tan(b))

  trig_basic_ax.arc_sin_cos: AXIOM
    sq(a) + sq(b) = sq(c) IMPLIES
     (EXISTS d: a = c * trig_basic_ax.cos(d) AND b = c * trig_basic_ax.sin(d))

  trig_basic_ax.pythagorean: LEMMA
    sq(a) + sq(b) = sq(nnc) IMPLIES
     (EXISTS (alpha: real):
        nnc = a * trig_basic_ax.cos(alpha) + b * trig_basic_ax.sin(alpha))

  trig_basic_ax.sin_2a: LEMMA
    trig_basic_ax.sin(2 * a) = 2 * trig_basic_ax.sin(a) * trig_basic_ax.cos(a)

  trig_basic_ax.cos_2a: LEMMA
    trig_basic_ax.cos(2 * a) =
     trig_basic_ax.cos(a) * trig_basic_ax.cos(a) -
      trig_basic_ax.sin(a) * trig_basic_ax.sin(a)

  trig_basic_ax.cos_2a_cos: LEMMA
    trig_basic_ax.cos(2 * a) =
     2 * trig_basic_ax.cos(a) * trig_basic_ax.cos(a) - 1

  trig_basic_ax.cos_2a_sin: LEMMA
    trig_basic_ax.cos(2 * a) =
     1 - 2 * trig_basic_ax.sin(a) * trig_basic_ax.sin(a)

  trig_basic_ax.tan_2a_TCC1: OBLIGATION
    FORALL (a: real):
      trig_basic_ax.tan(a) * trig_basic_ax.tan(a) /= 1 AND
       trig_basic_ax.Tan?(2 * a) AND trig_basic_ax.Tan?(a)
       IMPLIES (1 - trig_basic_ax.tan(a) * trig_basic_ax.tan(a)) /= 0;

  trig_basic_ax.tan_2a: LEMMA
    trig_basic_ax.Tan?(a) AND
     trig_basic_ax.Tan?(2 * a) AND
      trig_basic_ax.tan(a) * trig_basic_ax.tan(a) /= 1
     IMPLIES
     trig_basic_ax.tan(2 * a) =
      2 * trig_basic_ax.tan(a) /
       (1 - trig_basic_ax.tan(a) * trig_basic_ax.tan(a))

  trig_basic_ax.sin_period: LEMMA
    trig_basic_ax.sin(a) = trig_basic_ax.sin(a + 2 * j * trig_basic_ax.pi)

  trig_basic_ax.cos_period: LEMMA
    trig_basic_ax.cos(a) = trig_basic_ax.cos(a + 2 * j * trig_basic_ax.pi)

  trig_basic_ax.tan_period_TCC1: OBLIGATION
    FORALL (a: real, j: integer):
      trig_basic_ax.Tan?(a) IMPLIES
       trig_basic_ax.Tan?(a + j * trig_basic_ax.pi);

  trig_basic_ax.tan_period: LEMMA
    trig_basic_ax.Tan?(a) IMPLIES
     trig_basic_ax.tan(a) = trig_basic_ax.tan(a + j * trig_basic_ax.pi)

  trig_basic_ax.sin_k_pi: LEMMA trig_basic_ax.sin(k * trig_basic_ax.pi) = 0

  trig_basic_ax.cos_2k_pi: LEMMA
    trig_basic_ax.cos(2 * k * trig_basic_ax.pi) = 1

  trig_basic_ax.cos_k_pi: LEMMA
    trig_basic_ax.cos(k * trig_basic_ax.pi) = (-1) ^ (k)

  trig_basic_ax.sin_k_pi2: LEMMA
    trig_basic_ax.sin(k * trig_basic_ax.pi + trig_basic_ax.pi / 2) = (-1) ^ k

  trig_basic_ax.tan_k_pi_TCC1: OBLIGATION
    FORALL (k: integer): trig_basic_ax.Tan?(k * trig_basic_ax.pi);

  trig_basic_ax.tan_k_pi: LEMMA trig_basic_ax.tan(k * trig_basic_ax.pi) = 0

  trig_basic_ax.sin_eq_0: AXIOM
    trig_basic_ax.sin(a) = 0 IFF (EXISTS (i: int): a = i * trig_basic_ax.pi)

  trig_basic_ax.cos_eq_0: LEMMA
    trig_basic_ax.cos(a) = 0 IFF
     (EXISTS (i: int): a = i * trig_basic_ax.pi + trig_basic_ax.pi / 2)

  trig_basic_ax.sin_eq_0_2pi: COROLLARY
    0 <= a AND a <= 2 * trig_basic_ax.pi IMPLIES
     (trig_basic_ax.sin(a) = 0 IFF
       a = 0 OR a = trig_basic_ax.pi OR a = 2 * trig_basic_ax.pi)

  trig_basic_ax.cos_eq_0_2pi: COROLLARY
    0 <= a AND a <= 2 * trig_basic_ax.pi IMPLIES
     (trig_basic_ax.cos(a) = 0 IFF
       a = trig_basic_ax.pi / 2 OR a = 3 * trig_basic_ax.pi / 2)

  trig_basic_ax.tan_eq_0: LEMMA
    FORALL (a: (trig_basic_ax.Tan?)):
      (trig_basic_ax.tan(a) = 0 IFF
        (EXISTS (i: int): a = i * trig_basic_ax.pi))

  trig_basic_ax.sin_eq_1: LEMMA
    trig_basic_ax.sin(a) = 1 IFF
     (EXISTS (i: int): a = 2 * i * trig_basic_ax.pi + trig_basic_ax.pi / 2)

  trig_basic_ax.cos_eq_1: LEMMA
    trig_basic_ax.cos(a) = 1 IFF
     (EXISTS (i: int): a = 2 * i * trig_basic_ax.pi)

  trig_values_ax.sin_cos_pi4: LEMMA sin(pi / 4) = cos(pi / 4)

  trig_values_ax.cos_pi4: LEMMA cos(pi / 4) = 1 / sqrt(2)

  trig_values_ax.sin_pi4: LEMMA sin(pi / 4) = 1 / sqrt(2)

  trig_values_ax.cos_3pi4: LEMMA cos(3 * pi / 4) = -1 / sqrt(2)

  trig_values_ax.sin_3pi4: LEMMA sin(3 * pi / 4) = 1 / sqrt(2)

  trig_values_ax.tan_pi4_TCC1: OBLIGATION Tan?(pi / 4);

  trig_values_ax.tan_pi4: LEMMA tan(pi / 4) = 1

  trig_values_ax.sin_pi3_cos_pi6: LEMMA sin(pi / 3) = cos(pi / 6)

  trig_values_ax.sin_pi6_cos_pi3: LEMMA sin(pi / 6) = cos(pi / 3)

  trig_values_ax.sin_pi6: LEMMA sin(pi / 6) = 1 / 2

  trig_values_ax.cos_pi6: LEMMA cos(pi / 6) = sqrt(3) / 2

  trig_values_ax.tan_pi6_TCC1: OBLIGATION Tan?(pi / 6);

  trig_values_ax.tan_pi6: LEMMA tan(pi / 6) = 1 / sqrt(3)

  trig_values_ax.sin_pi3: LEMMA sin(pi / 3) = sqrt(3) / 2

  trig_values_ax.cos_pi3: LEMMA cos(pi / 3) = 1 / 2

  trig_values_ax.tan_pi3_TCC1: OBLIGATION Tan?(pi / 3);

  trig_values_ax.tan_pi3: LEMMA tan(pi / 3) = sqrt(3)

  trig_values_ax.sin_2pi3: LEMMA sin(2 * pi / 3) = sqrt(3) / 2

  trig_values_ax.cos_2pi3: LEMMA cos(2 * pi / 3) = -1 / 2

  trig_values_ax.tan_2pi3_TCC1: OBLIGATION Tan?(2 * pi / 3);

  trig_values_ax.tan_2pi3: LEMMA tan(2 * pi / 3) = -sqrt(3)

  trig_values_ax.cos_5pi4: LEMMA cos(5 * pi / 4) = -1 / sqrt(2)

  trig_values_ax.sin_5pi4: LEMMA sin(5 * pi / 4) = -1 / sqrt(2)

  trig_values_ax.sin_cos_5pi4: LEMMA sin(5 * pi / 4) = cos(5 * pi / 4)

  trig_ineq_ax.cos_gt_0: AXIOM -pi / 2 < a AND a < pi / 2 IMPLIES cos(a) > 0

  trig_ineq_ax.sin_gt_0: LEMMA 0 < a AND a < pi IMPLIES sin(a) > 0

  trig_ineq_ax.sin_ge_0: LEMMA 0 <= a AND a <= pi IMPLIES sin(a) >= 0

  trig_ineq_ax.cos_ge_0: LEMMA
    -pi / 2 <= a AND a <= pi / 2 IMPLIES cos(a) >= 0

  trig_ineq_ax.sin_lt_0: LEMMA pi < a AND a < 2 * pi IMPLIES sin(a) < 0

  trig_ineq_ax.cos_lt_0: LEMMA
    pi / 2 < a AND a < 3 * pi / 2 IMPLIES cos(a) < 0

  trig_ineq_ax.sin_le_0: LEMMA pi <= a AND a <= 2 * pi IMPLIES sin(a) <= 0

  trig_ineq_ax.cos_le_0: LEMMA
    pi / 2 <= a AND a <= 3 * pi / 2 IMPLIES cos(a) <= 0

  trig_ineq_ax.tan_gt_0_TCC1: OBLIGATION
    FORALL (a: real): a < pi / 2 AND 0 < a IMPLIES Tan?(a);

  trig_ineq_ax.tan_gt_0: LEMMA 0 < a AND a < pi / 2 IMPLIES tan(a) > 0

  trig_ineq_ax.tan_lt_0_TCC1: OBLIGATION
    FORALL (a: real): a < 0 AND -pi / 2 < a IMPLIES Tan?(a);

  trig_ineq_ax.tan_lt_0: LEMMA -pi / 2 < a AND a < 0 IMPLIES tan(a) < 0

  trig_ineq_ax.tan_pi2_def: LEMMA -pi / 2 < a AND a < pi / 2 IMPLIES Tan?(a)

  trig_ineq_ax.tan_npi_def: LEMMA Tan?(n * pi)

  trig_ineq_ax.cos_ge_0_3pi2: LEMMA
    3 * pi / 2 <= a AND a <= 2 * pi IMPLIES cos(a) >= 0

  trig_ineq_ax.sin_increasing_imp: LEMMA
         a <= pi / 2 AND a >= -pi / 2 AND b <= pi / 2 AND b >= -pi / 2
     AND a > b
     => sin(a) > sin(b)

  trig_ineq_ax.sin_increasing: LEMMA
    a <= pi / 2 AND a >= -pi / 2 AND b <= pi / 2 AND b >= -pi / 2 IMPLIES
     (sin(a) > sin(b) <=> a > b)

  trig_ineq_ax.sin_decreasing: LEMMA
    a <= 3 * pi / 2 AND a >= pi / 2 AND b <= 3 * pi / 2 AND b >= pi / 2
     IMPLIES (sin(b) > sin(a) <=> a > b)

  trig_ineq_ax.cos_increasing: LEMMA
    a >= pi AND a <= 2 * pi AND b >= pi AND b <= 2 * pi IMPLIES
     (cos(a) > cos(b) <=> a > b)

  trig_ineq_ax.cos_decreasing: LEMMA
    a <= pi AND a >= 0 AND b <= pi AND b >= 0 IMPLIES
     (cos(b) > cos(a) <=> a > b)

  trig_ineq_ax.tan_increasing_imp_TCC1: OBLIGATION
    FORALL (a, b: real):
           a > b AND b < pi / 2 AND -pi / 2 < b AND a < pi / 2
       AND -pi / 2 < a
       IMPLIES Tan?(a);

  trig_ineq_ax.tan_increasing_imp_TCC2: OBLIGATION
    FORALL (a, b: real):
           a > b AND b < pi / 2 AND -pi / 2 < b AND a < pi / 2
       AND -pi / 2 < a
       IMPLIES Tan?(b);

  trig_ineq_ax.tan_increasing_imp: LEMMA
         -pi / 2 < a AND a < pi / 2 AND -pi / 2 < b AND b < pi / 2 AND a > b
     IMPLIES tan(a) > tan(b)

  trig_ineq_ax.tan_increasing_TCC1: OBLIGATION
    FORALL (a, b: real):
      b < pi / 2 AND -pi / 2 < b AND a < pi / 2 AND -pi / 2 < a IMPLIES
       Tan?(a);

  trig_ineq_ax.tan_increasing_TCC2: OBLIGATION
    FORALL (a, b: real):
      b < pi / 2 AND -pi / 2 < b AND a < pi / 2 AND -pi / 2 < a IMPLIES
       Tan?(b);

  trig_ineq_ax.tan_increasing: LEMMA
    -pi / 2 < a AND a < pi / 2 AND -pi / 2 < b AND b < pi / 2 IMPLIES
     (tan(a) > tan(b) <=> a > b)

  trig_ineq_ax.sin_incr: LEMMA
    a <= pi / 2 AND a >= -pi / 2 AND b <= pi / 2 AND b >= -pi / 2 IMPLIES
     (sin(a) >= sin(b) <=> a >= b)

  trig_ineq_ax.sin_decr: LEMMA
    a <= 3 * pi / 2 AND a >= pi / 2 AND b <= 3 * pi / 2 AND b >= pi / 2
     IMPLIES (sin(b) >= sin(a) <=> a >= b)

  trig_ineq_ax.cos_incr: LEMMA
    a >= pi AND a <= 2 * pi AND b >= pi AND b <= 2 * pi IMPLIES
     (cos(a) >= cos(b) <=> a >= b)

  trig_ineq_ax.cos_decr: LEMMA
    a <= pi AND a >= 0 AND b <= pi AND b >= 0 IMPLIES
     (cos(b) >= cos(a) <=> a >= b)

  trig_ineq_ax.tan_incr: LEMMA
    -pi / 2 < a AND a < pi / 2 AND -pi / 2 < b AND b < pi / 2 IMPLIES
     (tan(a) >= tan(b) <=> a >= b)

  trig_ineq_ax.sin_gt: LEMMA
    -pi / 2 <= a AND a < 3 * pi / 2 AND -pi / 2 <= b AND b <= pi / 2 IMPLIES
     (sin(a) > sin(b) IFF b < a AND a < pi - b)

  trig_ineq_ax.sin_lt: LEMMA
    -pi / 2 <= a AND a < 3 * pi / 2 AND -pi / 2 <= b AND b <= pi / 2 IMPLIES
     (sin(a) < sin(b) IFF b > a OR a > pi - b)

  trig_ineq_ax.sin_ge: LEMMA
    -pi / 2 <= a AND a < 3 * pi / 2 AND -pi / 2 <= b AND b <= pi / 2 IMPLIES
     (sin(a) >= sin(b) IFF b <= a AND a <= pi - b)

  trig_basic_ax.trig_range: TYPE = {a | -1 <= a AND a <= 1}

  trig_basic_ax.trig_phase: TYPE+ = {x: nnreal | x < 2 * trig_basic_ax.pi}
        CONTAINING 0

  trig_basic_ax.sin(x: real): [real -> real];

  trig_basic_ax.cos(x: real): [real -> real];

  trig_basic_ax.Tan?(a): [real -> bool] = trig_basic_ax.cos(a) /= 0;

  trig_basic_ax.tan(a: (trig_basic_ax.Tan?)):
        [(trig_basic_ax.Tan?) -> real] =
      trig_basic_ax.sin(a) / trig_basic_ax.cos(a);

  trig_basic_ax.pi_lb: posreal = 31415926 / 10000000;

  trig_basic_ax.pi_ub: posreal = 31415927 / 10000000;

  trig_basic_ax.pi:
        {r: posreal | r > trig_basic_ax.pi_lb AND r < trig_basic_ax.pi_ub};


body:
  trig_full: THEORY
  %------------------------------------------------------------------------
  %
  % A Theory of Trigonometry
  %
  %       by Cesar Munoz
  %          Victor Carreno
  %          Ricky Butler
  %          Gilles Dowek
  %          Alfons Geser
  %          Ben Di Vito
  %          David Lester
  % 
  %------------------------------------------------------------------------

  BEGIN
     IMPORTING trig,
               trig_basic,    % basic properties 
               trig_values,   % values of functions for special arguments
               trig_ineq,     % trig inequalities
               trig_extra,    % sum and product, half-angle, reductions and zeros
               trig_approx,   % taylor series approximations to trig functions:
               tan_approx,    % approximatan2_propsations for tangent
               law_cosines,   % law of cosines
               trig_degree,   % conversions to degrees
               trig_inverses, % interface to atan, asin, acos, atan2
               trig_rew,      % auto-rewrites
               asin,          % asin properties
               acos,          % acos properties
               atan,          % atan properties
               atan_values,   % atan for specific values
               atan2,         % two-argument arc tangent
               atan2_props,   % additional properties of atan2 and values
               jatan2         % Java atan2

  END trig_full


body:
  trig_doc: THEORY
  %------------------------------------------------------------------------------
  %
  % Much of the foundational development was based on 
  % 
  %     Abramovitz and Stegun, "Handbook of Mathematical Functions" Dover.
  %     9th Edition (1972).
  % 
  % Approach:
  % 
  % (1) Define atan as an integral:  
  % 
  %	  atan(x) = Integral(0, x, (LAMBDA (x:real):1/(1+x*x)))  %  4.4.3
  % 
  % 
  % (2) Define atan, as having the same values as atan_value, but with
  %     source (-pi/2,pi/2).
  % 
  % (3) Prove it's a bijection.
  % 
  % (4) Define asin and acos, proving that they are bijections also:
  % 
  %	  asin(x:real_abs_le1): real_abs_le_pi2 =
  %	     IF x = -1 THEN -pi/2 ELSIF x < 1 
  %	     THEN atan(x/sqrt(1-x*x)) ELSE pi/2 ENDIF
  % 
  %	  acos(x:real_abs_le1):nnreal_le_pi = pi/2 - asin(x)
  % 
  % 
  % (5) Take advantage of a new theorem about the derivative 
  %     of an inverse function (derivative_inverse in analysis).
  % 
  % (6) Gradually expand the domain (source) of sin/cos definition from 
  %     (0,pi/4), firstly upto (0,2*pi) and then onto the whole real line.
  % 
  % (7) After establishing the derivatives, prove the series properties using
  %     Taylor's Theorem.
  % 
  % 
  % 
  % Some of David Lester's thoughts about why this is a better way to go than 
  % from infinite series definitions.
  % 
  % (1) At the time I wasn't too happy about arguing about infinite series, 
  %     and felt that basing the result on something more concrete would be 
  %     more useful.
  % 
  % (2) I think you run into some rather nasty and subtle circular reasoning 
  %     errors if you go down this route. The first problem will be to show 
  %     that $|sin(x)| <= 1$. Not circular, but not nice!
  % 
  % (3) I've remembered: at some stage you're going to have to show that
  %     (sin(x)/cos(x)) is bijective for x in the range (-pi/2,pi/2).
  %     Now, you could define pi = 4*atan(1), but I think you'll run into
  %     quite a few problems establishing the connections between these three 
  %     infinite series.
  % 
  %     Not quite circular reasoning (though I've been down quite a few of 
  %     those blind alleys recently!), but many of the results you think you 
  %     can rely on turn out to be unavailable for this reason.

  %------------------------------------------------------------------------------
  BEGIN
   
  END trig_doc


body:
  top: THEORY
  %------------------------------------------------------------------------
  %
  %    top_limits        -- Limit of a functions [T -> real] at a point  
  %    top_sequence      -- Limits and operations on sequences of reals
  %    top_continuity    -- Continuous functions [T -> real] 
  %    top_derivative    -- Differential Calculus  
  %    top_integral      -- Integral Calculus
  %
  %  See top_limits, top_sequences, top_continuity, top_derivative
  %  for summary of contents
  %
  %      by Bruno Dutertre     Royal Holloway & Bedford New College
  %         Rick Butler        NASA Langley Research Center
  %         Cesar Munoz        National Institute For Aerospace
  %         David Lester       Manchester University 
  %         Anthony Narkawicz  NASA Langley Research Center
  % 
  %      Version 1.0    last modified 7/12/96
  %      Version 1.1    updated to PVS 2.3   8/1/2000 by Rick Butler
  %      Version 1.2    updated to PVS 2.3   3/1/2001 by Bruno in
  %                     a slightly different way.
  %                     Bruno ELIMINATED "const_fun" and associated
  %                     conversion.  Now uses prelude "K_conversion".
  %                     RWB added back "const_fun" definition to
  %                     help with upward compatibility (real_fun_ops).
  %
  %                     Bruno changed "below_bounded" to "bounded_below?"
  %                           and changed structure of its definition.
  %                     Bruno changed "above_bounded" to "bounded_above?"
  %                           and changed structure of its definition.
  %      Version 1.3    Added theorem in derivatives_more 5/22/01
  %      Version 1.4    put back "const_fun" for PVS2.4
  %      Version 1.5    Used MACRO feature to rename all predicates
  %                     in real_fun_preds, adding ? to name    2/28/02
  %      Version 1.6    Added quadratic theory in "special_functions"  3/14/02
  %      Version 1.7    quadratic theory moved to reals
  %      Version 1.8    removed open? assugmption in integral theories 4/2/03
  %      Version 1.9    removed duplicates with reals library 4/14/03
  %      Version 2.0    proved step_function_integrable? in integral_step 
  %      Version 2.1    ln_exp moved to lnexp library (12/8/03)
  %      Version 2.2    David Lester added derivatives of inverse functions
  %                     and derivative of sqrt
  %      Version 2.3    NAME CHANGES -- See File NAME-CHANGES.txt
  %      Version 2.4    ADDED integral_chg_var and integral_diff_doms
  %      Version 2.5    NAME CHANGES: continuous2 --> cont_fun
  %      Version 2.6    moved nth_derivatives, and taylors here from series
  %      Version 2.7    add integration_by_parts and indefinite_integral 7/20/07
  %      Version 2.8    metric spaces, compactness, uniform continuity
  %
  %  NOTE: top_integral relies on the Di Vito strategy package
  %  NOTE: theories named  *_scaf are proof scaffolding, not intended for users
  %------------------------------------------------------------------------
  BEGIN

    IMPORTING top_limits, 
              top_sequences, 
              top_continuity,
              top_metric_spaces, 
              top_derivative,
  	    top_riesz_representation,
              top_integral  %  requires Manip strategies

  END top


body:
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  Sup and Inf of bounded functions  %
  %  (require nonempty domain)         %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  real_fun_supinf [ T : NONEMPTY_TYPE FROM real ] : THEORY

    BEGIN

    IMPORTING reals@real_fun_props, reals@real_facts


    f : VAR [T -> real]

    x : VAR T

    a : VAR real

    epsilon : VAR posreal


    %---------------
    %  Sup and Inf 
    %---------------

    g : VAR { f | bounded_above?(f) }

    h : VAR { f | bounded_below?(f) }


    nonempty_image: JUDGEMENT Im(f) HAS_TYPE (nonempty?[real])

    bounded_above_image: JUDGEMENT Im(g) HAS_TYPE (bounded_above?)

    bounded_below_image: JUDGEMENT Im(h) HAS_TYPE (bounded_below?)


    sup(g) : real = lub(Im(g))

    inf(h) : real = glb(Im(h))


    %--------------
    %  Properties
    %--------------

    supfun_is_bound : LEMMA   g(x) <= sup(g)

    supfun_is_sup : LEMMA
  	FORALL epsilon : EXISTS x : sup(g) - epsilon < g(x)

    supfun_is_sup2 : LEMMA
  	sup(g) <= a  IFF  FORALL x : g(x) <= a
   

    inffun_is_bound : LEMMA   inf(h) <= h(x)

    inffun_is_inf : LEMMA
  	FORALL epsilon : EXISTS x : h(x) < inf(h) + epsilon

    inffun_is_inf2 : LEMMA
  	a <= inf(h)  IFF  FORALL x : a <= h(x)



    supfun_neg : LEMMA  sup(- h) = - inf(h)

    inffun_neg : LEMMA  inf(- g) = - sup(g)


    %--------------------------------------
    %  Relations with maximum and minimum 
    %--------------------------------------

    max_upper_bound : LEMMA
  	is_maximum(x, f) IFF bounded_above?(f) AND sup(f) = f(x)
    

    min_lower_bound : LEMMA
  	is_minimum(x, f) IFF bounded_below?(f) AND inf(f) = f(x)

    END real_fun_supinf

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 31, column 28) for  Im(f)
      % expected type  (nonempty?[real])
  nonempty_image: OBLIGATION FORALL (f): nonempty?[real](Im[T](f));

  % Judgement subtype TCC generated (at line 33, column 33) for  Im(g)
      % expected type  (bounded_above?)
  bounded_above_image: OBLIGATION FORALL (g): bounded_above?(Im[T](g));

  % Judgement subtype TCC generated (at line 35, column 33) for  Im(h)
      % expected type  (bounded_below?)
  bounded_below_image: OBLIGATION FORALL (h): bounded_below?(Im[T](h));

  % Subtype TCC generated (at line 66, column 26) for  -h
      % expected type  {f | bounded_above?(f)}
  supfun_neg_TCC1: OBLIGATION
    FORALL (h: {f | bounded_below?(f)}): bounded_above?[T](-h);

  % Subtype TCC generated (at line 68, column 26) for  -g
      % expected type  {f | bounded_below?(f)}
  inffun_neg_TCC1: OBLIGATION
    FORALL (g: {f | bounded_above?(f)}): bounded_below?[T](-g);


body:
  sequence_props : THEORY
  %----------------------------------------------------------------------------
  %  Properties of real sequences              %
  %  -> condition for increasing? / decreasing %
  %  -> subsequences                           %
  %
  %  Author:  Bruno Dutertre    Royal Holloway & Bedford New College
  %----------------------------------------------------------------------------
  BEGIN

    IMPORTING real_fun_supinf

    u, v, w : VAR sequence[real]
    i, j : VAR nat
    a, x : VAR real
    n    : VAR nat

    %--------------------------------------------------
    %  Conditions for increasing?/decreasing sequences
    %--------------------------------------------------

    incr_condition        : LEMMA increasing?(u) IFF FORALL i : u(i) <= u(i+1)

    decr_condition        : LEMMA decreasing(u) IFF FORALL i : u(i+1) <= u(i)

    strict_incr_condition : LEMMA strict_increasing?(u) 
                                     IFF FORALL i : u(i) < u(i+1)

    strict_decr_condition : LEMMA strict_decreasing(u) 
                                     IFF FORALL i : u(i+1) < u(i)


    %-------------------------------------------------------
    %  Increasing sequences of natural numbers 
    %  used for extracting a sub-sequence from a sequence
    %-------------------------------------------------------

    extraction : TYPE = { f : [nat -> nat] | strict_increasing?(f) }

    f, g : VAR extraction

    extract_incr1      : LEMMA  f(i) < f(j) IFF i < j

    extract_incr2      : LEMMA  i <= j IMPLIES f(i) <= f(j)

    extract_incr3      : LEMMA  i <= f(i)

    unbounded_extract1 : LEMMA  EXISTS j : i <= f(j)

    unbounded_extract2 : LEMMA  EXISTS j : i < f(j)

    extract_composition : LEMMA  strict_increasing?(g o f)


    %-----------------
    %  Sub-sequences 
    %-----------------

    subseq(u, v) : bool = EXISTS f : FORALL i : u(i) = v(f(i))

    subseq_def:         LEMMA subseq(u,v) IFF EXISTS f: FORALL n: u(n) = v(f(n))

    reflexive_subseq :  LEMMA subseq(u, u)

    transitive_subseq : LEMMA subseq(u, v) AND subseq(v, w) IMPLIES subseq(u, w)

    extract_bij:        LEMMA bijective?[nat,(image(f,fullset[nat]))](f)

    %-----------------------------------------
    %  Properties inherited by subsequences
    %-----------------------------------------

    incr_subseq : LEMMA increasing?(v) AND subseq(u, v) IMPLIES increasing?(u)

    decr_subseq : LEMMA decreasing(v) AND subseq(u, v) IMPLIES decreasing(u)

    strict_incr_subseq  : LEMMA strict_increasing?(v) AND subseq(u, v)
  	                         IMPLIES strict_increasing?(u)

    strict_decr_subseq  : LEMMA strict_increasing?(v) AND subseq(u, v)
  	                         IMPLIES strict_increasing?(u)


    bounded_above_subseq: LEMMA bounded_above?(v) AND subseq(u, v) 
                                    IMPLIES bounded_above?(u)

    bounded_below_subseq: LEMMA bounded_below?(v) AND subseq(u, v) 
                                    IMPLIES bounded_below?(u)

    bounded_subseq      : LEMMA bounded?(v) AND subseq(u, v) IMPLIES bounded?(u)

  END sequence_props

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 67, column 68) for  f
      % expected type  [nat -> (image(f, fullset[nat]))]
  extract_bij_TCC1: OBLIGATION
    FORALL (f: extraction, x1: nat): image[nat, nat](f, fullset[nat])(f(x1));


body:
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  From any sequence one can extract           %
  %  an increasing or a decreasing sub-sequence  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  monotone_subsequence : THEORY

    BEGIN

    IMPORTING sequence_props

    u, s : VAR sequence[real]

    i, j, n : VAR nat
    


    %---------------------------------------------------
    %  If all the suffixes of v have a minimal element
    %  then v contains an increasing sub-sequence
    %---------------------------------------------------

    has_minimum(u, n) : bool =
  	EXISTS i : n <= i AND FORALL j : n <= j IMPLIES u(i) <= u(j)

    minimum_prefix : LEMMA
  	EXISTS i : FORALL j : j <= n IMPLIES u(i) <= u(j)

    minimum_suffix : LEMMA
  	has_minimum(u, n) IMPLIES has_minimum(u, 0)


    v : VAR { u | FORALL n : has_minimum(u, n) }


    %--- a minimum of the elements n, n+1, ....  ---%

    mini(v, n) : nat =
  	epsilon! i : n <= i AND FORALL j : n <= j IMPLIES v(i) <= v(j)

    min_prop : LEMMA
  	n <= mini(v, n) AND FORALL j : n <= j IMPLIES v(mini(v, n)) <= v(j)

    min_prop1 : COROLLARY  n <= mini(v, n)

    min_prop2 : COROLLARY  n <= i IMPLIES v(mini(v, n)) <= v(i)


    %--- subsequence ---%

    h(v)(i) : RECURSIVE nat =
  	IF i = 0
  	THEN mini(v, 0)
  	ELSE mini(v, h(v)(i - 1) + 1)
  	ENDIF
       MEASURE i

    hseq(v) : sequence[real] = LAMBDA i : v(h(v)(i))

    h_increasing : LEMMA strict_increasing?(h(v))

    hseq_extraction : LEMMA subseq(hseq(v), v)

    hseq_increasing : LEMMA increasing?(hseq(v))


      

    %------------------------------------------------------
    %  If a sequence has no minimal element it contains a 
    %  (strictly) decreasing sub-sequence
    %------------------------------------------------------

    w : VAR { u | not has_minimum(u, 0) }

    no_minimum : LEMMA not has_minimum(w, n)

    pick(w, n) : nat = epsilon! i : n <= i AND w(i) < w(n)

    pick_prop : LEMMA  n <= pick(w, n) AND w(pick(w, n)) < w(n)

    pick_prop1 : COROLLARY  n < pick(w, n)

    pick_prop2 : COROLLARY  w(pick(w, n)) < w(n)


    %--- subsequence ---%

    g(w)(i) : RECURSIVE nat =
  	IF i = 0
  	THEN pick(w, 0)
  	ELSE pick(w, g(w)(i - 1))
  	ENDIF
       MEASURE i

    gseq(w) : sequence[real] = LAMBDA i : w(g(w)(i))

    g_increasing : LEMMA strict_increasing?(g(w))

    gseq_extraction : LEMMA subseq(gseq(w), w)

    gseq_decreasing : LEMMA strict_decreasing(gseq(w))


    %------------------------
    %  Suffix starting at n
    %------------------------

    suffix(u, n) : sequence[real] = LAMBDA i : u(n+i)

    suffix_subseq : LEMMA subseq(suffix(u, n), u)

    suffix_hasmin : LEMMA
  	has_minimum(suffix(u, n), 0) IFF has_minimum(u, n)


    %----------------
    %  Main theorem
    %----------------

    monotone_subsequence : THEOREM
  	EXISTS s : subseq(s, u) AND (increasing?(s) OR decreasing(s))
   

    END monotone_subsequence

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 54, column 19) for  i - 1
      % expected type  nat
  h_TCC1: OBLIGATION
    FORALL (v: {u | FORALL n: has_minimum(u, n)}, i: nat):
      NOT i = 0 IMPLIES i - 1 >= 0;

  % Termination TCC generated (at line 54, column 14) for  h(v)(i - 1)
  h_TCC2: OBLIGATION
    FORALL (v: {u | FORALL n: has_minimum(u, n)}, i: nat):
      NOT i = 0 IMPLIES i - 1 < i;

  % Subtype TCC generated (at line 92, column 19) for  i - 1
      % expected type  nat
  g_TCC1: OBLIGATION
    FORALL (w: {u | NOT has_minimum(u, 0)}, i: nat):
      NOT i = 0 IMPLIES i - 1 >= 0;

  % Termination TCC generated (at line 92, column 14) for  g(w)(i - 1)
  g_TCC2: OBLIGATION
    FORALL (w: {u | NOT has_minimum(u, 0)}, i: nat):
      NOT i = 0 IMPLIES i - 1 < i;


body:
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  Definition and properties of      %
  %  convergent sequences of reals     %
  %  -> limit of a sequence,           %
  %  -> point of accumulation          %
  %  -> cauchy criterion		     %
  %  -> Bolzano-Weierstrass theorem    %
  %  -> completeness of the reals      %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  convergence_sequences : THEORY

    BEGIN

    IMPORTING sequence_props, reals@abs_lems,  monotone_subsequence

    u, u1, u2 : VAR sequence[real]

    l, l1, l2 : VAR real

    a, b, c, x : VAR real

    epsilon : VAR posreal

    i, j, n, m : VAR nat


    %--------------------
    %  Convergence to l
    %--------------------

    convergence(u, l) : bool =
  	FORALL epsilon : EXISTS n :
  	    FORALL i : i >= n IMPLIES abs(u(i) - l) < epsilon

    %-------------------------
    %  Point of accumulation
    %-------------------------

    accumulation(u, a) : bool =
  	FORALL epsilon, n : EXISTS i : i >= n AND abs(u(i) - a) < epsilon

    %--------------------
    %  Cauchy sequence
    %--------------------

    cauchy(u) : bool =
  	FORALL epsilon : EXISTS n :
  	    FORALL i, j : i >= n AND j >= n IMPLIES abs(u(i) - u(j)) < epsilon






    %-----------------------
    %  The limit is unique  
    %-----------------------

    unique_limit : LEMMA
  	convergence(u, l1) AND convergence(u, l2) IMPLIES l1 = l2



    %---------------------------------
    %  Limit of convergent sequences
    %---------------------------------

    convergent?(u) : bool = EXISTS l : convergence(u, l)

    convergent_seq?(u): MACRO bool = convergent?(u)

    v : VAR (convergent?)

    limit(v) : real = epsilon(LAMBDA l : convergence(v, l))

    limit_lemma : LEMMA convergence(v, limit(v))

    limit_def : LEMMA  limit(v) = l IFF convergence(v, l)



    %--------------------------------------------------------
    %  A subsequence of a convergent sequence is convergent
    %--------------------------------------------------------

    convergence_subsequence : LEMMA
  	convergence(u1, l) AND subseq(u2, u1) IMPLIES convergence(u2, l)

    

    %----------------------------------------
    %  The limit is a point of accumulation
    %----------------------------------------

    limit_accumulation : LEMMA 
  	convergence(u, l) IMPLIES accumulation(u, l)



    %------------------------------------------------------------------
    %  a is a point of accumulation iff a sub-sequence converges to a
    %------------------------------------------------------------------

    %--- extraction ---%

    g(u, a)(n) : RECURSIVE nat =
  	IF n = 0 THEN 0
  	ELSE  epsilon! i : g(u, a)(n - 1) < i AND abs(u(i) - a) < 1/n
  	ENDIF
        MEASURE n


    %--- property of g when a is an accumulation point of a ---%

    g_prop : LEMMA accumulation(u, a) IMPLIES
  	FORALL n : g(u, a)(n) < g(u, a)(n+1) AND abs(u(g(u, a)(n + 1)) - a) < 1/(n + 1)

    g_increasing : COROLLARY
  	accumulation(u, a) IMPLIES strict_increasing?(g(u, a))

    g_convergence : COROLLARY
  	accumulation(u, a) IMPLIES FORALL n : abs(u(g(u, a)(n + 1)) - a) < 1/(n + 1)


    %--- main theorem ---%

    accumulation_subsequence : THEOREM
  	accumulation(u, a) IFF EXISTS u1 : subseq(u1, u) AND convergence(u1, a)



    %-------------------------------------------------------------
    %  a point of accumulation of a Cauchy sequence is its limit
    %-------------------------------------------------------------

    cauchy_accumulation : THEOREM
  	cauchy(u) AND accumulation(u, a) IMPLIES convergence(u, a)

    cauchy_subsequence : COROLLARY
  	cauchy(u) AND subseq(u1, u) AND convergence(u1, l)
  	    IMPLIES convergence(u, l)




    %----------------------------------------------
    %  Monotone, bounded sequences are convergent 
    %----------------------------------------------

    v1 : VAR { u | bounded_above?(u) }

    v2 : VAR { u | bounded_below?(u) }

    increasing_bounded_convergence : LEMMA
  	increasing?(v1) IMPLIES convergence(v1, sup(v1))

    decreasing_bounded_convergence : LEMMA
  	decreasing(v2) IMPLIES convergence(v2, inf(v2))




    %--------------------------------------------------
    %  Bolzano-Weierstrass theorem:
    %  a bounded sequence has a point of accumulation
    %--------------------------------------------------

    %--- bounded sequence ---%

    w : VAR { u | bounded_above?(u) AND bounded_below?(u) }  

    
    %--- Bolzano/Weirstrass theorem ---%

    bolzano_weierstrass1 : COROLLARY
  	EXISTS a : inf(w) <= a AND a <= sup(w) AND accumulation(w, a)

    bolzano_weierstrass2 : COROLLARY  EXISTS a : accumulation(w, a)

    bolzano_weierstrass3 : COROLLARY
  	EXISTS u : subseq(u, w) AND convergent?(u)

    bolzano_weierstrass4 : COROLLARY
  	(FORALL i : a <= u(i) AND u(i) <= b) IMPLIES
  	    (EXISTS c : a <= c AND c <= b AND accumulation(u, c))




    %--------------------------------
    %  A Cauchy sequence is bounded
    %--------------------------------

    prefix_bounded1 : LEMMA
  	EXISTS a : FORALL i : i <= n IMPLIES u(i) <= a

    prefix_bounded2 : LEMMA
  	EXISTS a : FORALL i : i <= n IMPLIES a <= u(i)

    cauchy_bounded : LEMMA
  	cauchy(u) IMPLIES bounded_above?(u) AND bounded_below?(u)




    %--------------------------------------------------
    %  Completeness : a Cauchy sequence is convergent
    %--------------------------------------------------

    convergence_cauchy1 : LEMMA convergent?(u) IMPLIES cauchy(u)

    convergence_cauchy2 : LEMMA cauchy(u) IMPLIES convergent?(u)

    convergence_cauchy : THEOREM  convergent?(u) IFF cauchy(u)

    END convergence_sequences

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 109, column 28) for  n - 1
      % expected type  nat
  g_TCC1: OBLIGATION FORALL (n: nat): NOT n = 0 IMPLIES n - 1 >= 0;

  % Termination TCC generated (at line 109, column 20) for  g(u, a)(n - 1)
  g_TCC2: OBLIGATION FORALL (n: nat): NOT n = 0 IMPLIES n - 1 < n;

  % Subtype TCC generated (at line 109, column 61) for  n
      % expected type  nznum
  g_TCC3: OBLIGATION
    FORALL (u: sequence[real], a: real, n: nat,
            v: [[sequence[real], real] -> [{z1: nat | z1 < n} -> nat]]):
      NOT n = 0 IMPLIES (FORALL (i): v(u, a)(n - 1) < i IMPLIES n /= 0);


body:
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  Lemmas used for limits of product and inverse
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  epsilon_lemmas : THEORY
  BEGIN

    x1, x2, y1, y2 : VAR real
    e, e1, e2 : VAR posreal

    IMPORTING reals@real_facts, reals@abs_lems

    %--- Lemmas for product ---%

    prod_bound : LEMMA
  	abs(x1 - y1) < e1 AND abs(x2 - y2) < e2 IMPLIES 
  	abs(x1 * x2 - y1 * y2) < e1 * e2 + abs(y1) * e2 + abs(y2) * e1

    prod_epsilon : LEMMA
  	EXISTS e1, e2 : e1 * e2 + abs(y1) * e2 + abs(y2) * e1 < e


    %--- Lemmas for inverse ---%

    inv_bound : LEMMA
  	abs(x1 - y1) < e1 and e1 < abs(y1) and x1 /= 0 and y1 /= 0 
  	IMPLIES abs(1/x1 - 1/y1) < e1 / (abs(y1) * (abs(y1) - e1))

    inv_epsilon1 : LEMMA
  	y1 /= 0 IMPLIES 
  	   EXISTS e1 : e1 < abs(y1) and e1 < e * (abs(y1) - e1)

    inv_epsilon : LEMMA 
  	y1 /= 0  IMPLIES
  	   EXISTS e1 : e1 < abs(y1) 
  		   and e1 / (abs(y1) * (abs(y1) - e1)) < e


  % Proof "By varying epsilon"
  %
  % A technique to get the inequalities to run the "wrong way" for
  % epsilon. Can be used to give yourself a small extra quantity to play with
  % in analysis proofs.
  % 

    epsilon: VAR posreal
    x,y:     VAR real

    varying_epsilon: LEMMA x <= y <=> (FORALL epsilon: x <= y + epsilon)


  END epsilon_lemmas

addendum:
  %%% ================ Addendum: generated declarations ================

  % Subtype TCC generated (at line 27, column 34) for
      % (abs(y1) * (abs(y1) - e1))
      % expected type  nznum
  inv_bound_TCC1: OBLIGATION
    FORALL (e1: posreal, x1, y1: real):
      y1 /= 0 AND x1 /= 0 AND e1 < abs(y1) AND abs(x1 - y1) < e1 IMPLIES
       (abs(y1) * (abs(y1) - e1)) /= 0;

  % Subtype TCC generated (at line 36, column 15) for
      % (abs(y1) * (abs(y1) - e1))
      % expected type  nznum
  inv_epsilon_TCC1: OBLIGATION
    FORALL (y1: real):
      y1 /= 0 IMPLIES
       (FORALL (e1): e1 < abs(y1) IMPLIES (abs(y1) * (abs(y1) - e1)) /= 0);


body:
  convergence_ops : THEORY
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  Limits and operations on sequences of reals
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  BEGIN

    IMPORTING convergence_sequences, epsilon_lemmas


    s, s1, s2 : VAR sequence[real]

    s3 : VAR sequence[nzreal]

    a : VAR real

    l, l1, l2 : VAR real

    n, m, N : VAR nat



    %---------------------------------
    %  limits of sum, product, etc.
    %---------------------------------

    cnv_seq_sum : LEMMA
  		convergence(s1, l1) AND convergence(s2, l2) 
  	IMPLIES convergence(s1 + s2, l1 + l2)

    cnv_seq_neg : LEMMA
  		convergence(s1, l1)
  	IMPLIES convergence(-s1, -l1)

    cnv_seq_diff : LEMMA
  		convergence(s1, l1) AND convergence(s2, l2) 
  	IMPLIES convergence(s1 - s2, l1 - l2)	

    cnv_seq_prod : LEMMA
  		convergence(s1, l1) AND convergence(s2, l2) 
  	IMPLIES convergence(s1 * s2, l1 * l2)

    cnv_seq_const : LEMMA  convergence(const_fun(a), a)

    cnv_seq_scal : LEMMA
  	convergence(s1, l1) IMPLIES convergence(a * s1, a * l1)

    cnv_seq_inv : LEMMA
  		convergence(s3, l2)  AND l2 /= 0
  	IMPLIES convergence(1 / s3, 1 / l2)

    cnv_seq_div : LEMMA
  		convergence(s1, l1) AND convergence(s3, l2) 
  	    AND l2 /= 0
  	IMPLIES convergence(s1 / s3, l1 / l2)

    cnv_seq_abs : LEMMA
  	convergence(s1, l1) IMPLIES convergence(abs(s1), abs(l1))


    cnv_seq_order : LEMMA
  		convergence(s1, l1) and convergence(s2, l2)
  	    AND (FORALL n : s1(n) <= s2(n))
  	IMPLIES l1 <= l2

    convergence_shift: LEMMA convergence(s,l) IFF
                                convergence(LAMBDA n: s(n+m),l)



    %-------------
    %  Squeezing
    %-------------

    squeezing_variant : LEMMA
  	    	convergence(s1, l) and convergence(s2, l)
  	    AND	(FORALL n : N <= n IMPLIES s1(n) <= s(n) and s(n) <= s2(n))
  	IMPLIES convergence(s, l)

    squeezing_const1 : LEMMA
  		convergence(s1, l)
  	    AND (FORALL n : N <= n IMPLIES l <= s(n) AND s(n) <= s1(n))
  	IMPLIES convergence(s, l)

    squeezing_const2 : LEMMA
  		convergence(s1, l)
  	    AND (FORALL n : N <= n IMPLIES s1(n) <= s(n) AND s(n) <= l)
  	IMPLIES convergence(s, l)

    squeezing : LEMMA
  	    	convergence(s1, l) and convergence(s2, l)
  	    AND (FORALL n : s1(n) <= s(n) and s(n) <= s2(n))
  	IMPLIES convergence(s, l)


    squeezing_gen : LEMMA
  	    	convergence(s1, l) and convergence(s2, l)
  	    AND (FORALL n : n >= N IMPLIES s1(n) <= s(n) and s(n) <= s2(n))
  	IMPLIES convergence(s, l)

    abs_convergence : COROLLARY
  	convergence(s, 0) IFF convergence(abs(s), 0)


    %----------------------------------
    %  Same properties with convergent
    %----------------------------------

    convergent_sum : LEMMA
  	convergent?(s1) AND convergent?(s2) IMPLIES convergent?(s1 + s2)

    convergent_neg : LEMMA
  	convergent?(s1) IMPLIES convergent?(-s1)

    convergent_diff : LEMMA
  	convergent?(s1) AND convergent?(s2) IMPLIES convergent?(s1 - s2)	

    convergent_prod : LEMMA
  	convergent?(s1) AND convergent?(s2) IMPLIES convergent?(s1 * s2)

    convergent_const : LEMMA  convergent?(const_fun(a))

    convergent_scal : LEMMA
  	convergent?(s1) IMPLIES convergent?(a * s1)

    convergent_inv : LEMMA
  	convergent?(s3) AND limit(s3) /= 0 IMPLIES convergent?(1 / s3)

    convergent_div : LEMMA
  	convergent?(s1) AND convergent?(s3) AND limit(s3) /= 0
  	IMPLIES convergent?(s1 / s3)

    convergent_abs : LEMMA
  	convergent?(s1) IMPLIES convergent?(abs(s1))

    squeezing_abs_0 : LEMMA               % BUTLER
  	    	convergence(s1, 0) 
  	    AND (FORALL n : abs(s(n)) <= s1(n))
  	IMPLIES convergence(s, 0)

    squeezing_abs_0_gen : LEMMA            % BUTLER
  	    	(convergence(s1, 0) 
  	    AND (EXISTS N: (FORALL n : n >= N IMPLIES abs(s(n)) <= s1(n))))
  	IMPLIES convergence(s, 0)




    %--------------------------------- 
    %  Types of convergent sequences
    %---------------------------------

    v1, v2 : VAR (convergent?)

    u : VAR { s3 | convergent?(s3) }

    convergent_nz?(u) : bool = limit(u) /= 0

    v3 : VAR (convergent_nz?)

    %--------------
    %  Judgements
    %--------------

    constant_seq1: JUDGEMENT const_fun(a) HAS_TYPE (convergent?)

    constant_seq2: JUDGEMENT const_fun(b: nzreal) HAS_TYPE (convergent_nz?)

    conv_seq_plus:  JUDGEMENT +(v1, v2) HAS_TYPE (convergent?)

    conv_seq_minus: JUDGEMENT -(v1, v2) HAS_TYPE (convergent?)

    conv_seq_times: JUDGEMENT *(v1, v2) HAS_TYPE (convergent?)

    conv_seq_scal: JUDGEMENT *(a, v1) HAS_TYPE (convergent?)

    conv_seq_neg: JUDGEMENT -(v1) HAS_TYPE (convergent?)

    conv_seq_abs: JUDGEMENT abs(v1) HAS_TYPE (convergent?)

    conv_seq_div1: JUDGEMENT /(v1, v3) HAS_TYPE (convergent?)

    conv_seq_div2: JUDGEMENT /(a, v3) HAS_TYPE (convergent?)



    %-----------------------------
    %  Combinations of sequences
    %-----------------------------

    limit_sum      : LEMMA limit(v1 + v2) = limit(v1) + limit(v2)

    limit_neg : LEMMA limit(- v1) = - limit(v1)

    limit_diff     : LEMMA limit(v1 - v2) = limit(v1) - limit(v2)

    limit_prod     : LEMMA limit(v1 * v2) = limit(v1) * limit(v2)

    limit_inv      : LEMMA limit(1 / v3) = 1 / limit(v3)

    limit_div      : LEMMA limit(v1 / v3) = limit(v1) / limit(v3)

    limit_const    : LEMMA limit(const_fun(a)) = a

    limit_scal     : LEMMA limit(a * v1) = a * limit(v1)
    
    limit_abs      : LEMMA limit(abs(v1)) = abs(limit(v1))



    %---------------------------------------------------
    %  Expansion of convergence (for computing limits)
    %---------------------------------------------------

    limit_equiv : LEMMA
  	convergence(s, l) IFF convergent?(s) AND limit(s) = l


    limit_order : PROPOSITION
                  convergence(s1, l1) AND convergence(s2, l2)
              AND (FORALL n : s1(n) <= s2(n))
          => l1 <= l2

  %----------------------------------------------------------------------------
  % NOTE: See "convergence_special" in lnexp library for convergence of
  % sequences involving x^a where a is real
  %
  % NOTE: See "series" in series library for convergence of |x|^n and x^n
  %----------------------------------------------------------------------------
  END convergence_ops

addendum:
  %%% ================ Addendum: generated declarations ================

  % Judgement subtype TCC generated (at line 165, column 27) for  const_fun(a)
      % expected type  (convergent?)
  constant_seq1: OBLIGATION FORALL (a): convergent?(const_fun[nat](a));

  % Judgement subtype TCC generated (at line 167, column 27) for  const_fun(b)
      % expected type  (convergent_nz?)
  constant_seq2: OBLIGATION
    FORALL (b: nzreal):
      (FORALL (x1: nat): const_fun[nat](b)(x1) /= 0) AND
       convergent?(const_fun[nat](b)) AND convergent_nz?(const_fun[nat](b));

  % Judgement subtype TCC generated (at line 169, column 28) for  v1 + v2
      % expected type  (convergent?)
  conv_seq_plus: OBLIGATION FORALL (v1, v2): convergent?((+[nat])(v1, v2));

  % Judgement subtype TCC generated (at line 171, column 28) for  v1 - v2
      % expected type  (convergent?)
  conv_seq_minus: OBLIGATION FORALL (v1, v2): convergent?((-[nat])(v1, v2));

  % Judgement subtype TCC generated (at line 173, column 28) for  v1 * v2
      % expected type  (convergent?)
  conv_seq_times: OBLIGATION FORALL (v1, v2): convergent?(*[nat](v1, v2));

  % Judgement subtype TCC generated (at line 175, column 27) for  a * v1
      % expected type  (convergent?)
  conv_seq_scal: OBLIGATION FORALL (a, v1): convergent?(*[nat](a, v1));

  % Judgement subtype TCC generated (at line 177, column 26) for  -v1
      % expected type  (convergent?)
  conv_seq_neg: OBLIGATION FORALL (v1): convergent?(-v1);

  % Judgement subtype TCC generated (at line 179, column 26) for  abs(v1)
      % expected type  (convergent?)
  conv_seq_abs: OBLIGATION FORALL (v1): convergent?(abs[nat](v1));

  % Judgement subtype TCC generated (at line 181, column 27) for  v1 / v3
      % expected type  (convergent?)
  conv_seq_div1: OBLIGATION FORALL (v1, v3): convergent?(/[nat](v1, v3));

  % Judgement subtype TCC generated (at line 183, column 27) for  a / v3
      % expected type  (convergent?)
  conv_seq_div2: OBLIGATION FORALL (a, v3): convergent?(/[nat](a, v3));

  % Subtype TCC generated (at line 199, column 45) for  limit(v3)
      % expected type  nznum
  limit_inv_TCC1: OBLIGATION FORALL (v3: (convergent_nz?)): limit(v3) /= 0;


body:
  top_sequences : THEORY

    BEGIN

    IMPORTING convergence_ops, convergence_sequences

    END top_sequences


body:
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  General convergence of functions [T -> real]  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  convergence_functions [T : TYPE FROM real] : THEORY
  BEGIN

    IMPORTING reals@real_fun_ops, epsilon_lemmas

    epsilon, delta : VAR posreal
    e, e1, e2 : VAR posreal
    E, E1, E2 : VAR setof[real]
    f, f1, f2 : VAR [T -> real]
    g : VAR [T -> nzreal]
    l, l1, l2, a, b, z : VAR real
    x, y : VAR T

    %---------------------------
    %  Reals adherent to a set
    %---------------------------

    adh(E) : setof[real] =
  	{ z | FORALL e : EXISTS x : E(x) AND abs(x - z) < e }


    member_adherent : LEMMA   E(x) IMPLIES adh(E)(x)

    adherence_subset1 : LEMMA
  	subset?(E1, E2) AND adh(E1)(z) IMPLIES adh(E2)(z)

    adherence_subset2 : LEMMA
  	subset?(E1, E2) IMPLIES subset?(adh(E1), adh(E2))


    adherence_prop1 : LEMMA
  	FORALL e, E, (a : (adh(E))) :
  	    EXISTS x : E(x) AND abs(x - a) < e

    adherence_prop2 : LEMMA 
  	FORALL e1, e2, E, (a : (adh(E))) :
  	    EXISTS x : E(x) AND abs(x - a) < e1 AND abs(x - a) < e2



    %------------------------------------------------------
    %  Definition of convergence and immediate properties
    %------------------------------------------------------

    convergence(f, E, a, l) : bool = 
  	adh(E)(a) AND 
  	FORALL epsilon : EXISTS delta : 
  	    FORALL x : E(x) AND abs(x - a) < delta IMPLIES abs(f(x) - l) < epsilon

    convergence_unicity : LEMMA
  	FORALL E, f, a, l1, l2 : 
  	    convergence(f, E, a, l1) AND convergence(f, E, a, l2)
          IMPLIES l1 = l2

    subset_convergence : LEMMA
  	subset?(E1, E2) IMPLIES
  	    FORALL f, (a : (adh(E1))), l :
  	        convergence(f, E2, a, l) IMPLIES convergence(f, E1, a, l)

    subset_convergence2 : LEMMA
  	FORALL E1, E2, f, (a : (adh(E1))), l :
  	    subset?(E1, E2) AND convergence(f, E2, a, l)
  	 	IMPLIES convergence(f, E1, a, l)

    convergence_in_domain : LEMMA
  	FORALL f, x, l : E(x) AND convergence(f, E, x, l) IMPLIES l = f(x)




    %----------------------------------
    %  Limits and function operations
    %----------------------------------

    convergence_sum : LEMMA
  	FORALL E, f1, f2, a, l1, l2 :
  		convergence(f1, E, a, l1) 
  	    AND convergence(f2, E, a, l2)
          IMPLIES convergence(f1 + f2, E, a, l1 + l2)


    convergence_neg : LEMMA
  	FORALL E, f1, a, l1 :
  		convergence(f1, E, a, l1) 
          IMPLIES convergence(- f1, E, a, - l1)


    convergence_diff : LEMMA
  	FORALL E, f1, f2, a, l1, l2 :
  		convergence(f1, E, a, l1) 
  	    AND convergence(f2, E, a, l2)
          IMPLIES convergence(f1 - f2, E, a, l1 - l2)


    convergence_prod : LEMMA
  	FORALL E, f1, f2, a, l1, l2 :
  		convergence(f1, E, a, l1) 
  	    AND convergence(f2, E, a, l2)
          IMPLIES convergence(f1 * f2, E, a, l1 * l2)


    convergence_const : LEMMA
  	FORALL E, (a : (adh(E))), b : convergence(const_fun(b), E, a, b)


    convergence_scal : LEMMA
  	FORALL E, f1, a, l1, b :
  		convergence(f1, E, a, l1)
  	IMPLIES convergence(b * f1, E, a, b * l1)


    convergence_inv : LEMMA
  	FORALL E, g, a, l1:
  		convergence(g, E, a, l1)
  	    AND l1 /= 0
  	IMPLIES convergence(1/g, E, a, 1/l1)


    convergence_div : LEMMA
  	FORALL E, f, g, a, l1, l2 :
  		convergence(f, E, a, l1)
  	    AND convergence(g, E, a, l2)
  	    AND l2 /= 0
  	IMPLIES convergence(f/g, E, a, l1/l2)
  	


    %---------------------
    %  Identity function
    %---------------------

    convergence_identity : LEMMA 
  	FORALL E, (a : (adh(E))) : convergence(I[T], E, a, a)



    %-----------------------------
    %  Limit preserve order
    %-----------------------------

    convergence_order : LEMMA
  	FORALL E, f1, f2, a, l1, l2 :
  		convergence(f1, E, a, l1)
  	    AND convergence(f2, E, a, l2)
  	    AND (FORALL x : E(x) IMPLIES f1(x) <= f2(x))
  	IMPLIES l1 <= l2
    

    %-------------------------------------------
    %  Bounds on function are bounds on limits
    %-------------------------------------------

    convergence_lower_bound : COROLLARY
  	FORALL E, f, b, a, l :
  		convergence(f, E, a, l)
  	    AND (FORALL x : E(x) IMPLIES b <= f(x))
  	IMPLIES b <= l

    convergence_upper_bound : COROLLARY
  	FORALL E, f, b, a, l :
  		convergence(f, E, a, l)
  	    AND (FORALL x : E(x) IMPLIES f(x) <= b)
  	IMPLIES l <= b


    %--------------------------
    %  Function constant on E
    %--------------------------

    convergence_locally_constant : LEMMA
  	FORALL E, f, b, (a : (adh(E))) :
  	    (FORALL x : E(x) IMPLIES f(x) = b)
  	IMPLIES convergence(f, E, a, b)
    

    %-------------
    %  Squeezing
    %-------------

    convergence_squeezing : LEMMA
  	FORALL f1, f2, f, a, l :
  	    convergence(f1, E, a, l) AND convergence(f2, E, a, l)
  	AND (FORALL x : E(x) IMPLIES f1(x) <= f(x) AND f(x) <= f2(x))
      IMPLIES
  	    convergence(f, E, a, l)


  END convergence_functions


body:
  lim_of_functions [ T : TYPE FROM real ] : THEORY
  %----------------------------------------------------------------------------
  %  Limit of a functions [T -> real] at a point a   %
  %
  %  Author:  Bruno Dutertre    Royal Holloway & Bedford New College
  %----------------------------------------------------------------------------
  BEGIN

    IMPORTING convergence_functions

    %------------------------------------------------
    %  Subtype of reals where the limit makes sense
    %------------------------------------------------

    a, b, l, l1, l2 : VAR real
    c : VAR (adh[T](fullset[real]))
    f, f1, f2 : VAR [ T -> real]
    g : VAR [T -> nzreal]
    epsilon, delta : VAR posreal
    x : VAR T

    %---------------------------------------------------
    %  Convergence of f at a point a towards a limit l
    %---------------------------------------------------

    convergence(f, a, l) : bool = convergence(f, fullset[real], a, l)

    convergence_def : LEMMA
          FORALL f, a, l :
              convergence(f, a, l)
          IFF
              adh[T](fullset[real])(a)
          AND FORALL epsilon : EXISTS delta :
                  FORALL x : abs(x - a) < delta IMPLIES abs(f(x) - l) < epsilon


    adherence_fullset : LEMMA adh[T](fullset[real])(x)

    cv_unique    : LEMMA convergence(f, a, l1) AND convergence(f, a, l2)
                        IMPLIES l1 = l2

    cv_in_domain : LEMMA convergence(f, x, l) IMPLIES l = f(x)

    %-------------------------------------------
    %  convergence and operations on functions
    %-------------------------------------------

    cv_sum   : LEMMA convergence(f1, a, l1) AND convergence(f2, a, l2)
                       IMPLIES convergence(f1 + f2, a, l1 + l2)

    cv_diff  : LEMMA convergence(f1, a, l1) AND convergence(f2, a, l2)
                       IMPLIES convergence(f1 - f2, a, l1 - l2)

    cv_prod  : LEMMA convergence(f1, a, l1) AND convergence(f2, a, l2)
                       IMPLIES convergence(f1 * f2, a, l1 * l2)

    cv_const : LEMMA convergence(const_fun(b), c, b)

    cv_scal  : LEMMA convergence(f, a, l)
                       IMPLIES convergence(b * f, a, b * l)

    cv_neg   : LEMMA convergence(f, a, l)
                       IMPLIES convergence(- f, a, - l)

    cv_div   : LEMMA convergence(f, a, l1) AND convergence(g, a, l2) AND l2 /= 0
                       IMPLIES convergence(f / g, a, l1 / l2)

    cv_inv   : LEMMA convergence(g, a, l) AND l /= 0
                       IMPLIES convergence(1 / g, a, 1 / l)

    cv_identity: LEMMA convergence(I[T], c, c)
          
    cv_abs   : LEMMA convergence(abs, c, abs(c))
          
    conv_0_0_abs: LEMMA convergence(f, 0, 0) IFF convergence(abs(f), 0, 0)


    %-------------------------
    %  f is convergent at a    
    %-------------------------

    convergent?(f, a) : bool = EXISTS l : convergence(f, a, l)

  %  lim(f, (x0 : {a | convergent?(f, a)})) : real =  
  %        choose(LAMBDA l : convergence(f, x0, l))


    lim(f, (x0 : {a | convergent?(f, a)})) : {l: real |  convergence(f, x0, l)}

    lim_fun_lemma   : LEMMA FORALL f, (x0 : {a | convergent?(f, a)}) :
                            convergence(f, x0, lim(f, x0))

    lim_fun_def     : LEMMA FORALL f, l, (x0 : {a | convergent?(f, a)}) :
                               lim(f, x0) = l IFF convergence(f, x0, l)

    lim_e_del: LEMMA convergent?(f, a) IMPLIES
      (lim(f, a) = l IFF FORALL (e: posreal): EXISTS (del: posreal): FORALL (x: T):
                             abs(x-a) < del IMPLIES abs(f(x) - l) < e)

    convergence_equiv    : LEMMA convergence(f, a, l) IFF 
                                    convergent?(f, a) AND lim(f, a) = l
          
    convergent_in_domain : LEMMA convergent?(f, x) IFF convergence(f, x, f(x))
          
    lim_in_domain        : LEMMA convergent?(f, x) IMPLIES lim(f, x) = f(x)
          

    %------------------------------------------
    %  Operations preserving convergence at a 
    %------------------------------------------

    sum_fun_convergent  : LEMMA convergent?(f1, a) AND convergent?(f2, a)
                                  IMPLIES convergent?(f1 + f2, a)

    neg_fun_convergent : LEMMA convergent?(f, a) IMPLIES convergent?(- f, a)
          
    diff_fun_convergent : LEMMA convergent?(f1, a) AND convergent?(f2, a)
                                  IMPLIES convergent?(f1 - f2, a)

    prod_fun_convergent : LEMMA convergent?(f1, a) AND convergent?(f2, a)
                                  IMPLIES convergent?(f1 * f2, a)

    const_fun_convergent: LEMMA convergent?(const_fun(b), c)
          
    scal_fun_convergent : LEMMA convergent?(f, a) IMPLIES convergent?(b * f, a)
          
    inv_fun_convergent  : LEMMA convergent?(g, a) AND lim(g, a) /= 0
                                   IMPLIES convergent?(1/g, a)

    div_fun_convergent  : LEMMA convergent?(f, a) AND convergent?(g, a)
                                  AND lim(g, a) /= 0 IMPLIES convergent?(f / g, a)

    convergent_identity : LEMMA convergent?(I[T], c)


    %----------------------------
    %  Same things with lim(a)
    %----------------------------

    lim_sum_fun      : LEMMA convergent?(f1, a) AND convergent?(f2, a)
                               IMPLIES lim(f1 + f2, a) = lim(f1, a) + lim(f2, a)

    lim_neg_fun : LEMMA convergent?(f, a) 
                               IMPLIES lim(- f, a) = - lim(f, a)
          
    lim_diff_fun     : LEMMA convergent?(f1, a) AND convergent?(f2, a)
                               IMPLIES lim(f1 - f2, a) = lim(f1, a) - lim(f2, a)

    lim_prod_fun     : LEMMA convergent?(f1, a) AND convergent?(f2, a)
                               IMPLIES lim(f1 * f2, a) = lim(f1, a) * lim(f2, a)

    lim_const_fun    : LEMMA lim(const_fun(b), c) = b

    lim_scal_fun     : LEMMA convergent?(f, a) 
                               IMPLIES lim(b * f, a) = b * lim(f, a)
          
    lim_inv_fun      : LEMMA convergent?(g, a) AND lim(g, a) /= 0
                               IMPLIES lim(1/g, a) = 1/lim(g, a)

    lim_div_fun  : LEMMA convergent?(f, a) AND convergent?(g, a) AND lim(g, a) /= 0
                               IMPLIES lim(f / g, a) = lim(f, a)/lim(g, a)

    lim_identity : LEMMA lim(I[T], c) = c
    



    %--------------------
    %  Bounds on limits
    %--------------------

    E : VAR setof[real]

    lim_le1 : LEMMA
          convergent?(f, a) AND (FORALL x : f(x) <= b) IMPLIES lim(f, a) <= b

    lim_ge1 : LEMMA
          convergent?(f, a) AND (FORALL x : f(x) >= b) IMPLIES lim(f, a) >= b
    
    lim_order1 : LEMMA convergent?(f1, a) AND convergent?(f2, a)
                       AND (FORALL x : f1(x) <= f2(x)) 
                           IMPLIES lim(f1, a) <= lim(f2, a)

    lim_le2    : LEMMA convergent?(f, a) AND adh[T](E)(a) AND 
                       (FORALL x : E(x) IMPLIES f(x) <= b) 
                           IMPLIES lim(f, a) <= b

    lim_ge2    : LEMMA convergent?(f, a) AND adh[T](E)(a) AND 
                       (FORALL x : E(x) IMPLIES f(x) >= b) 
                           IMPLIES lim(f, a) >= b

    lim_order2 : LEMMA convergent?(f1, a) AND convergent?(f2, a)  AND adh[T](E)(a)
                       AND (FORALL x : E(x) IMPLIES f1(x) <= f2(x))
                           IMPLIES lim(f1, a) <= lim(f2, a)


    AUTO_REWRITE+ adherence_fullset



  END lim_of_functions

addendum:
  %%% ================ Addendum: generated declarations ================

  % Existence TCC generated (at line 88, column 2) for
      % lim(f, (x0: {a | convergent?(f, a)})):
      %       {l: real | convergence(f, x0, l)}
  lim_TCC1: OBLIGATION
    EXISTS (x:
              [d: [f: [T -> real], {a | convergent?(f, a)}] ->
                 {l: real | convergence(d`1, d`2, l)}]):
      TRUE;

  % Subtype TCC generated (at line 141, column 50) for  a
      % expected type  {a | convergent?(f1 + f2, a)}
  lim_sum_fun_TCC1: OBLIGATION
    FORALL (a: real, f1, f2: [T -> real]):
      convergent?(f2, a) AND convergent?(f1, a) IMPLIES
       convergent?((+[T])(f1, f2), a);

  % Subtype TCC generated (at line 144, column 46) for  a
      % expected type  {a | convergent?(-f, a)}
  lim_neg_fun_TCC1: OBLIGATION
    FORALL (a: real, f: [T -> real]):
      convergent?(f, a) IMPLIES convergent?(-f, a);

  % Subtype TCC generated (at line 147, column 50) for  a
      % expected type  {a | convergent?(f1 - f2, a)}
  lim_diff_fun_TCC1: OBLIGATION
    FORALL (a: real, f1, f2: [T -> real]):
      convergent?(f2, a) AND convergent?(f1, a) IMPLIES
       convergent?((-[T])(f1, f2), a);

  % Subtype TCC generated (at line 150, column 50) for  a
      % expected type  {a | convergent?(f1 * f2, a)}
  lim_prod_fun_TCC1: OBLIGATION
    FORALL (a: real, f1, f2: [T -> real]):
      convergent?(f2, a) AND convergent?(f1, a) IMPLIES
       convergent?(*[T](f1, f2), a);

  % Subtype TCC generated (at line 152, column 45) for  c
      % expected type  {a | convergent?(const_fun(b), a)}
  lim_const_fun_TCC1: OBLIGATION
    FORALL (b: real, c: (adh[T](fullset[real]))):
      convergent?(const_fun[T](b), c);

  % Subtype TCC generated (at line 155, column 48) for  a
      % expected type  {a | convergent?(b * f, a)}
  lim_scal_fun_TCC1: OBLIGATION
    FORALL (a, b: real, f: [T -> real]):
      convergent?(f, a) IMPLIES convergent?(*[T](b, f), a);

  % Subtype TCC generated (at line 158, column 46) for  a
      % expected type  {a | convergent?(1 / g, a)}
  lim_inv_fun_TCC1: OBLIGATION
    FORALL (a: real, g: [T -> nzreal]):
      lim(g, a) /= 0 AND convergent?(g, a) IMPLIES convergent?(/[T](1, g), a);

  % Subtype TCC generated (at line 161, column 48) for  a
      % expected type  {a | convergent?(f / g, a)}
  lim_div_fun_TCC1: OBLIGATION
    FORALL (a: real, f: [T -> real], g: [T -> nzreal]):
      lim(g, a) /= 0 AND convergent?(g, a) AND convergent?(f, a) IMPLIES
       convergent?(/[T](f, g), a);

  % Subtype TCC generated (at line 163, column 33) for  c
      % expected type  {a | convergent?(I[T], a)}
  lim_identity_TCC1: OBLIGATION
    FORALL (c: (adh[T](fullset[real]))): convergent?(I[T], c);


body:
  %----------------------------------------------------------------------------
  %  Continuous functions [ T -> real]   
  % 
  %  Defines:
  %      continuous?(f, x0)                  ---- continuity at a point
  %      continuous?(f, E)                   ---- continuity on a set
  %
  %  I some cases PVS has trouble disambiguating these, so the following are
  %  defined which helps.  See cont_if_fun for an example.
  %
  %      continuous_at?(f, x0)               ---- continuity at a point
  %      continuous_on?(f, E)                ---- continuity on a set
  %
  %
  %
  %----------------------------------------------------------------------------


  continuous_functions [ T : TYPE FROM real ] : THEORY
  BEGIN

    IMPORTING lim_of_functions


    f, f1, f2      : VAR [T -> real]
    g              : VAR [T -> nzreal]
    u              : VAR real
    x, x0          : VAR T
    epsilon, delta : VAR posreal
    n              : VAR nat
   


    %--------------------
    %  Continuity at x0    
    %--------------------

    continuous?(f, x0) : bool = 
              FORALL epsilon : EXISTS delta : FORALL x :
                  abs(x - x0) < delta IMPLIES abs(f(x) - f(x0)) < epsilon


    continuous_at?(f, x0) : MACRO bool = continuous?(f, x0)

    %--- equivalent definitions ---%

    continuity_def : LEMMA
          continuous?(f, x0) IFF convergence(f, x0, f(x0))

    continuity_def2 : LEMMA
          continuous?(f, x0) IFF convergent?(f, x0)


    %---------------------------------------------
    %  Continuity of f in a subset of its domain
    %---------------------------------------------

    E: VAR setof[T]

    continuous_on?(f, E): bool = FORALL (x0: (E)): FORALL epsilon:
       EXISTS delta: FORALL (x:(E)): abs(x - x0) < delta IMPLIES abs(f(x) - f(x0)) < epsilon


    continuous_on_def: LEMMA
        continuous_on?(f, E) IFF FORALL (y: (E)): convergence(f, E, y, f(y))



    %------------------------------------------
    %  Operations preserving continuity at x0 
    %------------------------------------------

    sum_continuous  : LEMMA continuous?(f1, x0) AND continuous?(f2, x0)
                             IMPLIES continuous?(f1 + f2, x0)

    diff_continuous : LEMMA continuous?(f1, x0) AND continuous?(f2, x0)
                             IMPLIES continuous?(f1 - f2, x0)

    prod_continuous : LEMMA continuous?(f1, x0) AND continuous?(f2, x0)
                             IMPLIES continuous?(f1 * f2, x0)

    const_continuous: LEMMA continuous?(const_fun(u), x0)

    scal_continuous : LEMMA continuous?(f, x0) IMPLIES continuous?(u * f, x0)
                  
    neg_continuous  : LEMMA continuous?(f, x0) IMPLIES continuous?(- f, x0)

    div_continuous  : LEMMA continuous?(f, x0) AND continuous?(g, x0) 
                              IMPLIES continuous?(f/g, x0)

    inv_continuous  : LEMMA continuous?(g, x0) IMPLIES continuous?(1/g, x0)
    
    identity_continuous: LEMMA continuous?(I[T], x0)

    expt_continuous : LEMMA continuous?(f, x0) IMPLIES continuous?(f^n, x0)


    %---------------------------------------------
    %  Continuity of f in a subset of its domain
    %---------------------------------------------

    F: VAR setof[real]


    %--- Operation preserving continuity in E ---%

    sum_set_continuous :  LEMMA continuous_on?(f1, E) AND continuous_on?(f2, E)
                                 IMPLIES continuous_on?(f1 + f2, E)

    diff_set_continuous : LEMMA continuous_on?(f1, E) AND continuous_on?(f2, E)
                                 IMPLIES continuous_on?(f1 - f2, E)
   
    prod_set_continuous : LEMMA continuous_on?(f1, E) AND continuous_on?(f2, E)
                                 IMPLIES continuous_on?(f1 * f2, E)

    const_set_continuous: LEMMA continuous_on?(const_fun(u), E)

    scal_set_continuous : LEMMA continuous_on?(f, E) IMPLIES continuous_on?(u * f, E)

    neg_set_continuous  : LEMMA continuous_on?(f, E) IMPLIES continuous_on?(- f, E)

    div_set_continuous  : LEMMA continuous_on?(f, E) AND continuous_on?(g, E) 
                                IMPLIES continuous_on?(f/g, E)

    inv_set_continuous  : LEMMA continuous_on?(g, E) IMPLIES continuous_on?(1/g, E)
    
    identity_set_continuous: LEMMA continuous_on?(I[T], E)

    
    %---------------------------------
    %  Continuity of f in its domain
    %---------------------------------

    continuous?(f): bool = FORALL x0: continuous?(f, x0)

    continuous_def2: LEMMA continuous?(f) IFF continuous_on?(f, T_pred)  

    continuity_subset2: LEMMA continuous?(f) IMPLIES continuous_on?(f, E)


    %--- Properties ---%

    continuous_fun: TYPE+ = { f | continuous?(f) }

    nz_continuous_fun: TYPE = { g | continuous?(g) }

    h, h1, h2: VAR continuous_fun
    h3: VAR nz_continuous_fun

    sum_fun_continuous : JUDGEMENT  +(h1, h2) HAS_TYPE continuous_fun

    diff_fun_continuous: JUDGEMENT  -(h1, h2) HAS_TYPE continuous_fun

    prod_fun_continuous: JUDGEMENT  *(h1, h2) HAS_TYPE continuous_fun

    const_fun_continuous: JUDGEMENT const_fun(u) HAS_TYPE continuous_fun

    scal_fun_continuous: JUDGEMENT  *(u, h) HAS_TYPE continuous_fun

    neg_fun_continuous  : JUDGEMENT -(h) HAS_TYPE continuous_fun

    div_fun_continuous : JUDGEMENT /(h, h3) HAS_TYPE continuous_fun

    id_fun_continuous  : JUDGEMENT I[T] HAS_TYPE continuous_fun



    inv_fun_continuous : LEMMA continuous?(1/h3)


    m,b: VAR real
    linear_fun_cont    : LEMMA continuous?(LAMBDA x: m*x + b) %% BUTLER

    one_over_x_cont    : LEMMA (FORALL x: x /= 0) IMPLIES
                                         continuous?((LAMBDA x: 1 / x))

    x_to_n_continuous  : LEMMA continuous?(LAMBDA x: x^n)   %% BUTLER

    expt_fun_continuous: LEMMA continuous?(f) IMPLIES continuous?(f^n)



  % ------------ Alternate forms and names for convenience ---------------

    sum_cont_fun  : LEMMA continuous?(f1) AND continuous?(f2)
                             IMPLIES continuous?(f1 + f2)

    diff_cont_fun : LEMMA continuous?(f1) AND continuous?(f2)
                             IMPLIES continuous?(f1 - f2)

    prod_cont_fun : LEMMA continuous?(f1) AND continuous?(f2)
                             IMPLIES continuous?(f1 * f2)

    const_cont_fun: LEMMA continuous?(const_fun(u))

    scal_cont_fun : LEMMA continuous?(f) IMPLIES continuous?(u * f)
                  
    neg_cont_fun    : LEMMA continuous?(f) IMPLIES continuous?(- f)

    div_cont_fun  : LEMMA continuous?(f) AND continuous?(g) 
                              IMPLIES continuous?(f/g)

    inv_cont_fun  : LEMMA continuous?(g) IMPLIES continuous?(1/g)
    
    identity_cont_fun: LEMMA continuous?(I[T])

  %  id_cont_fun      : LEMMA continuous?(LAMBDA (t: posreal): t)

    expt_cont_fun    : LEMMA continuous?(f) IMPLIES continuous?(f^n)


  END continuous_functions

addendum:
  %%% ================ Addendum: generated declarations ================

  % Existence TCC generated (at line 143, column 2) for
      % continuous_fun: TYPE+ = {f | continuous?(f)}
  continuous_fun_TCC1: OBLIGATION EXISTS (x: {f | continuous?(f)}): TRUE;

  % Judgement subtype TCC generated (at line 150, column 34) for  h1 + h2
      % expected type  continuous_fun
  sum_fun_continuous: OBLIGATION FORALL (h1, h2): continuous?((+[T])(h1, h2));

  % Judgement subtype TCC generated (at line 152, column 34) for  h1 - h2
      % expected type  continuous_fun
  diff_fun_continuous: OBLIGATION
    FORALL (h1, h2): continuous?((-[T])(h1, h2));

  % Judgement subtype TCC generated (at line 154, column 34) for  h1 * h2
      % expected type  continuous_fun
  prod_fun_continuous: OBLIGATION FORALL (h1, h2): continuous?(*[T](h1, h2));

  % Judgement subtype TCC generated (at line 156, column 34) for  const_fun(u)
      % expected type  continuous_fun
  const_fun_continuous: OBLIGATION FORALL (u): continuous?(const_fun[T](u));

  % Judgement subtype TCC generated (at line 158, column 34) for  u * h
      % expected type  continuous_fun
  scal_fun_continuous: OBLIGATION FORALL (h, u): continuous?(*[T](u, h));

  % Judgement subtype TCC generated (at line 160, column 34) for  -h
      % expected type  continuous_fun
  neg_fun_continuous: OBLIGATION FORALL (h): continuous?(-h);

  % Judgement subtype TCC generated (at line 162, column 33) for  h / h3
      % expected type  continuous_fun
  div_fun_continuous: OBLIGATION FORALL (h, h3): continuous?(/[T](h, h3));

  % Judgement subtype TCC generated (at line 164, column 33) for  I[T]
      % expected type  continuous_fun
  id_fun_continuous: OBLIGATION continuous?(I[T]);

  % Subtype TCC generated (at line 175, column 66) for  x
      % expected type  nznum
  one_over_x_cont_TCC1: OBLIGATION
    (FORALL x: x /= 0) IMPLIES (FORALL (x1): x1 /= 0);

  % Subtype TCC generated (at line 177, column 53) for  n
      % expected type  {i: int | x /= 0 OR i >= 0}
  x_to_n_continuous_TCC1: OBLIGATION FORALL (n: nat, x): x /= 0 OR n >= 0;


body:
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %  Properties of continuous functions     %
  %  in relation with sequences, limits     %
  %  and points of accumulation             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  continuity_props[T : TYPE FROM real] : THEORY

    BEGIN

    IMPORTING continuous_functions, top_sequences

    f : VAR [T -> real]

    u : VAR sequence[T]

    l, a : VAR T


    %--------------------------------------------
    %  u is convergent to l and f is continuous
    %--------------------------------------------

    continuity_limit : LEMMA
  	convergence(u, l) AND continuous?(f, l)
  	     IMPLIES convergence(f o u, f(l))


    %--------------------------------------------
    %  point of accumulation
    %--------------------------------------------

    continuity_accumulation : LEMMA
  	accumulation(u, a) AND continuous?(f, a)
  	    IMPLIES accumulation(f o u, f(a))
    

    END continuity_props


body:
  continuity_interval [ a : real, b : {x : real | a <= x }] : THEORY
  %-----------------------------------------------------------------
  %  continuous functions on a closed interval                     
  %-----------------------------------------------------------------
  BEGIN

    %-----------------------------
    %  Interval [a, b] as a type
    %-----------------------------

    x : VAR real
    J : NONEMPTY_TYPE = { x | a <= x AND x <= b}
    f : VAR [J -> real]
    u : VAR sequence[J]
    c : VAR J
    n, i : VAR nat

    IMPORTING continuity_props

    %-----------------------------------------------
    %  Reformulation of Bolzano/Weirstrass theorem
    %-----------------------------------------------

    bolz_weier : LEMMA   EXISTS c : accumulation(u, c)


    %-------------------------------------
    %  If f is continuous, it is bounded
    %-------------------------------------

    unbounded_sequence : LEMMA bounded_above?(f) OR 
                                 EXISTS u : FORALL n : f(u(n)) > n

    bounded_from_above : LEMMA continuous?(f) IMPLIES bounded_above?(f)

    bounded_from_below : LEMMA continuous?(f) IMPLIES bounded_below?(f)


    %--------------------------------------
    %  f has a maximum and a minimum in J
    %--------------------------------------

    max_extraction : LEMMA continuous?(f) IMPLIES
  	                   EXISTS u : FORALL n : sup(f) - f(u(n)) < 1/(n+1)

    sup_is_reached : LEMMA continuous?(f) IMPLIES EXISTS c : f(c) = sup(f)

    maximum_exists : LEMMA continuous?(f) IMPLIES EXISTS c : is_maximum(c, f)

    max_pt(f:{f|continuous?(f)}): {xj: J | is_maximum(xj,f)}     % ADDED BY RWB

    inf_is_reached : LEMMA continuous?(f) IMPLIES EXISTS c : f(c) = inf(f)

    minimum_exists : LEMMA continuous?(f) IMPLIES EXISTS c : is_minimum(c, f)

    min_pt(f:{f|continuous?(f)}): {xj: J | is_minimum(xj,f)}     % ADDED BY RWB


    %-------------------------------
    %  Intermediate value theorem
    %-------------------------------

    intermediate_value1 : LEMMA continuous?(f) AND f(a) < x AND x < f(b)
  	                        IMPLIES EXISTS c : f(c) = x

    intermediate_value2 : LEMMA continuous?(f) AND f(a) <= x AND x <= f(b)
  	                        IMPLIES EXISTS c : f(c) = x

    intermediate_value3 : LEMMA continuous?(f) AND f(b) < x AND x < f(a)
  	                        IMPLIES EXISTS c : f(c) = x

    intermediate_value4 : LEMMA continuous?(f) AND f(b) <= x AND x <= f(a)
  	                        IMPLIES EXISTS c : f(c) = x

  END continuity_interval

addendum:
  %%% ================ Addendum: generated declarations ================

  % Existence TCC generated (at line 12, column 2) for
      % J: TYPE+ = {x | a <= x AND x <= b}
  J_TCC1: OBLIGATION EXISTS (x1: {x | a <= x AND x <= b}): TRUE;

  % Subtype TCC generated (at line 44, column 46) for  f
      % expected type  {f | bounded_above?[J](f)}
  max_extraction_TCC1: OBLIGATION
    FORALL (f: [J -> real]): continuous?(f) IMPLIES bounded_above?[J](f);

  % Existence TCC generated (at line 50, column 2) for
      % max_pt(f: {f | continuous?(f)}): {xj: J | is_maximum?(xj, f)}
  max_pt_TCC1: OBLIGATION
    EXISTS (x:
              [f: {f | continuous?[J](f)} ->
                 {xj: J | is_maximum?[J](xj, f)}]):
      TRUE;

  % Subtype TCC generated (at line 52, column 70) for  f
      % expected type  {f | bounded_below?[J](f)}
  inf_is_reached_TCC1: OBLIGATION
    FORALL (f: [J -> real]): continuous?(f) IMPLIES bounded_below?[J](f);

  % Existence TCC generated (at line 56, column 2) for
      % min_pt(f: {f | continuous?(f)}): {xj: J | is_minimum?(xj, f)}
  min_pt_TCC1: OBLIGATION
    EXISTS (x:
              [f: {f | continuous?[J](f)} ->
                 {xj: J | is_minimum?[J](xj, f)}]):
      TRUE;

  % Subtype TCC generated (at line 63, column 51) for  a
      % expected type  J
  intermediate_value1_TCC1: OBLIGATION
    FORALL (f: [J -> real]): continuous?(f) IMPLIES a <= a AND a <= b;

  % Subtype TCC generated (at line 63, column 68) for  b
      % expected type  J
  intermediate_value1_TCC2: OBLIGATION
    FORALL (f: [J -> real], x: real):
      continuous?(f) AND f(a) < x IMPLIES a <= b AND b <= b;

  % Subtype TCC generated (at line 66, column 70) for  b
      % expected type  J
  intermediate_value2_TCC1: OBLIGATION
    FORALL (f: [J -> real], x: real):
      continuous?(f) AND f(a) <= x IMPLIES a <= b AND b <= b;

  % Subtype TCC generated (at line 69, column 51) for  b
      % expected type  J
  intermediate_value3_TCC1: OBLIGATION
    FORALL (f: [J -> real]): continuous?(f) IMPLIES a <= b AND b <= b;


