let e_app f args =
if not (simpl()) then Tapp(f,args)
else
match f , args with
| "neg_int" , [ Tapp( "neg_int" , [a] ) ] -> a
| "neg_real" , [ Tapp( "neg_real" , [a] ) ] -> a
| "neg_int" , [ Tconst (ConstInt a) ] ->
i_apply Big_int.minus_big_int a
| "add_int" , [ Tconst (ConstInt a) ; Tconst (ConstInt b) ] ->
i_compute Big_int.add_big_int a b
| "sub_int" , [ Tconst (ConstInt a) ; Tconst (ConstInt b) ] ->
i_compute Big_int.sub_big_int a b
| "mul_int" , [ Tconst (ConstInt a) ; Tconst (ConstInt b) ] ->
i_compute Big_int.mult_big_int a b
| "add_int" , [ Tconst (ConstInt "0") ; x ] -> x
| "add_int" , [ x ; Tconst (ConstInt "0") ] -> x
| "sub_int" , [ x ; Tconst (ConstInt "0") ] -> x
| "mul_int" , [ Tconst (ConstInt "1") ; x ] -> x
| "mul_int" , [ x ; Tconst (ConstInt "1") ] -> x
| "mul_int" , [ (Tconst (ConstInt "0")) as z ; _ ] -> z
| "mul_int" , [ _ ; (Tconst (ConstInt "0")) as z ] -> z
| "add_int" , [ b ; Tapp("sub_int",[a;c]) ] when eq_terms b c -> a ;
| "add_int" , [ Tapp("sub_int",[a;b]) ; c ] when eq_terms b c -> a
| "sub_int" , [ Tapp("add_int",[a;b]) ; c ] when eq_terms b c -> a
| "encode" , [ Tapp("decode" , [ a ; fmt ]) ; fmt' ] when eq_terms fmt fmt' -> a
| "decode" , [ Tapp("encode" , [ a ; fmt ]) ; fmt' ] when eq_terms fmt fmt' -> a
| "as_int" , [Tapp(fmt,[]) ; Tconst(ConstInt z)] -> as_int_format fmt z
| f , [Tconst(ConstInt z)] -> as_int f z
| f , [Tapp(g,[d])] -> coercion f g d
| _ -> Tapp (f, args)