(* ========================================================================= *)
(* Basic definitions and properties of complex numbers.                      *)
(* ========================================================================= *)
needs "Library/transc.ml";;
prioritize_real();;
(* ------------------------------------------------------------------------- *)
(* Definition of complex number type.                                        *)
(* ------------------------------------------------------------------------- *)
let complex_tybij_raw =
  new_type_definition "complex" ("complex","coords")
   (prove(`?x:real#real. T`,REWRITE_TAC[]));;
let complex_tybij = REWRITE_RULE [] complex_tybij_raw;;
(* ------------------------------------------------------------------------- *)
(* Real and imaginary parts of a number.                                     *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Set up overloading.                                                       *)
(* ------------------------------------------------------------------------- *)
do_list overload_interface
 ["+",`complex_add:complex->complex->complex`;
  "-",`complex_sub:complex->complex->complex`;
  "*",`complex_mul:complex->complex->complex`;
  "/",`complex_div:complex->complex->complex`;
  "--",`complex_neg:complex->complex`;
  "pow",`complex_pow:complex->num->complex`;
  "inv",`complex_inv:complex->complex`];;
let prioritize_complex() = prioritize_overload(mk_type("complex",[]));;
(* ------------------------------------------------------------------------- *)
(* Complex absolute value (modulus).                                         *)
(* ------------------------------------------------------------------------- *)
make_overloadable "norm" `:A->real`;;
overload_interface("norm",`complex_norm:complex->real`);;
let complex_norm = new_definition
  `norm(z) = sqrt(Re(z) pow 2 + Im(z) pow 2)`;;
let CX_DEF = new_definition
  `Cx(a) = complex(a,&0)`;;
let complex_neg = new_definition
  `--z = complex(--(Re(z)),--(Im(z)))`;;
let complex_add = new_definition
  `w + z = complex(Re(w) + Re(z),Im(w) + Im(z))`;;
let complex_mul = new_definition
  `w * z = complex(Re(w) * Re(z) - Im(w) * Im(z),
                   Re(w) * Im(z) + Im(w) * Re(z))`;;let complex_inv = new_definition
  `inv(z) = complex(Re(z) / (Re(z) pow 2 + Im(z) pow 2),
                    --(Im(z)) / (Re(z) pow 2 + Im(z) pow 2))`;;let complex_pow = new_recursive_definition num_RECURSION
  `(x pow 0 = Cx(&1)) /\
   (!n. x pow (SUC n) = x * x pow n)`;;
let COMPLEX_ADD_AC = prove
 (`(m + n = n + m) /\ ((m + n) + p = m + n + p) /\ (m + n + p = n + m + p)`,
  SIMPLE_COMPLEX_ARITH_TAC);;
 
let COMPLEX_MUL_AC = prove
 (`(m * n = n * m) /\ ((m * n) * p = m * n * p) /\ (m * n * p = n * m * p)`,
  SIMPLE_COMPLEX_ARITH_TAC);;
 
let COMPLEX_POLY_CLAUSES = prove
 (`(!x y z. x + (y + z) = (x + y) + z) /\
   (!x y. x + y = y + x) /\
   (!x. Cx(&0) + x = x) /\
   (!x y z. x * (y * z) = (x * y) * z) /\
   (!x y. x * y = y * x) /\
   (!x. Cx(&1) * x = x) /\
   (!x. Cx(&0) * x = Cx(&0)) /\
   (!x y z. x * (y + z) = x * y + x * z) /\
   (!x. x pow 0 = Cx(&1)) /\
   (!x n. x pow (SUC n) = x * x pow n)`,
  REWRITE_TAC[
complex_pow] THEN SIMPLE_COMPLEX_ARITH_TAC)
and COMPLEX_POLY_NEG_CLAUSES = 
prove
 (`(!x. --x = Cx(-- &1) * x) /\
   (!x y. x - y = x + Cx(-- &1) * y)`,
  SIMPLE_COMPLEX_ARITH_TAC);;
 
let COMPLEX_INV_INV = prove
 (`!x:complex. inv(inv x) = x`,
  GEN_TAC THEN ASM_CASES_TAC `x = Cx(&0)` THEN
  ASM_REWRITE_TAC[
COMPLEX_INV_0] THEN
  POP_ASSUM MP_TAC THEN
  MAP_EVERY (fun t -> MP_TAC(SPEC t 
COMPLEX_MUL_RINV))
   [`x:complex`; `inv(x):complex`] THEN
  CONV_TAC COMPLEX_RING);;