let coerce_merge_numeric (e1 : expr) (e2 : expr) =
match type_of e1, type_of e2 with
{ct_ty = Tbuiltin bt1}, {ct_ty = Tbuiltin bt2} ->
let merged_type =
match bt1, bt2 with
Tlongdouble, _ | _, Tlongdouble -> Tlongdouble
| Tdouble, _ | _, Tdouble -> Tdouble
| Tfloat, _ | _, Tfloat -> Tfloat
| Tulonglong, _ | _, Tulonglong -> Tulonglong
| (Tlonglong, _ | _, Tlonglong) when sizeof_longlong > sizeof_long -> Tlonglong
| (Tulong, _ | _, Tulong) -> Tulong
| (Tlonglong, _ | _, Tlonglong) when sizeof_longlong > sizeof_int -> Tlonglong
| (Tlong, _ | _, Tlong) when sizeof_long > sizeof_int -> Tlong
| Tuint, _ | _, Tuint -> Tuint
| Tlonglong, _ | _, Tlonglong -> Tlonglong
| Tlong, _ | _, Tlong -> Tlong
| (Tushort, _ | _, Tushort) when sizeof_short = sizeof_int -> Tuint
| (Tuchar, _ | _, Tuchar) when sizeof_char = sizeof_int -> Tuint
| (Tchar, _ | _, Tchar) when sizeof_char = sizeof_int && char_is_signed -> Tuint
| Tint, _ | _, Tint -> Tint
| _ -> Tint
in
let e1 = if bt1 = merged_type then e1 else arithmetic_coerce e1 (type_of e2) in
let e2 = if bt1 = merged_type then e2 else arithmetic_coerce e2 (type_of e1) in
e1, e2
| {ct_ty = Tbuiltin bt1}, _ ->
raise (TypeError_typed(e2, "not a numeric"))
| _ ->
raise (TypeError_typed(e1, "not a numeric"))