let rec e_prim f ts =
if not (simpl()) then Tprim(f,ts) else
match f , ts with
| I_opp , [ Tprim(I_opp,[a]) ] -> a
| R_opp , [ Tprim(R_opp,[a]) ] -> a
| I_add , [ Tint a ; Tint b ] -> i_compute My_bigint.add a b
| I_sub , [ Tint a ; Tint b ] -> i_compute My_bigint.sub a b
| I_mul , [ Tint a ; Tint b ] -> i_compute My_bigint.mul a b
| I_add , [ Tint "0" ; x ] -> x
| I_add , [ x ; Tint "0" ] -> x
| I_sub , [ Tint "0" ; x ] -> e_prim I_opp [x]
| I_sub , [ x ; Tint "0" ] -> x
| I_opp , [ Tint a ] -> i_compute My_bigint.sub "0" a
| I_mul , [ Tint "1" ; x ] -> x
| I_mul , [ x ; Tint "1" ] -> x
| I_mul , [ Tint "0" ; _ ] -> e_zero
| I_mul , [ _ ; Tint "0" ] -> e_zero
| I_add , [ b ; Tprim(I_sub,[a;c]) ] when equal b c -> a ;
| I_add , [ Tprim(I_sub,[a;b]) ; c ] when equal b c -> a
| I_sub , [ Tprim(I_add,[a;b]) ; c ] when equal b c -> a
| L_eq , [ Tint a ; Tint b ] -> i_compare (fun r -> r=0) a b
| L_neq , [ Tint a ; Tint b ] -> i_compare (fun r -> r<>0) a b
| I_lt , [ Tint a ; Tint b ] -> i_compare (fun r -> r<0) a b
| L_eq , [a;b] when equal a b -> Ttrue
| L_neq , [a;b] when equal a b -> Tfalse
| I_leq , [ Tint a ; Tint b ] -> i_compare (fun r -> r<=0) a b
| I_of_R , [ Tprim(R_of_I,[a]) ] -> a
| B_not , [p] -> e_not p
| B_and , [a;b] -> e_and a b
| B_or , [a;b] -> e_or a b
| _ -> Tprim(f,ts)