let eval_binop_float ~with_alarms ev1 op ev2 = 
  try
    let conv v = 
      try Ival.project_float (V.project_ival v)
      with
        | V.Not_based_on_null
        | Ival.Float_abstract.Nan_or_infinite ->
            warning_once_current "converting value to float: assert(Ook)";
            Ival.Float_abstract.top
    in
    let f1 = conv ev1
    and f2 = conv ev2
    in
    let binary_float_floats (_name: string) f =
      try
        let alarm, f = f (get_rounding_mode ()) f1 f2 in
        if alarm then CilE.warn_result_nan_infinite with_alarms;
        V.inject_ival (Ival.inject_float f)
      with
        | Ival.Float_abstract.Nan_or_infinite ->
            CilE.warn_result_nan_infinite with_alarms ;
            V.top_float
        | Ival.Float_abstract.Bottom ->
            CilE.warn_result_nan_infinite with_alarms ;
            V.bottom
    in
    begin match op with
      | PlusA ->   binary_float_floats "+." Ival.Float_abstract.add_float
      | MinusA ->  binary_float_floats "-." Ival.Float_abstract.sub_float
      | Mult ->    binary_float_floats "*." Ival.Float_abstract.mult_float
      | Div ->     binary_float_floats "/." Ival.Float_abstract.div_float
      | Eq ->
          let contains_zero, contains_non_zero =
            Ival.Float_abstract.equal_float_ieee f1 f2
          in
          V.interp_boolean ~contains_zero ~contains_non_zero
      | Ne ->
          let contains_non_zero, contains_zero =
            Ival.Float_abstract.equal_float_ieee f1 f2
          in
          V.interp_boolean ~contains_zero ~contains_non_zero
      | Lt ->
          V.interp_boolean
            ~contains_zero:(Ival.Float_abstract.maybe_le_ieee_float f2 f1)
            ~contains_non_zero:(Ival.Float_abstract.maybe_lt_ieee_float f1 f2)
      | Le ->
          V.interp_boolean
            ~contains_zero:(Ival.Float_abstract.maybe_lt_ieee_float f2 f1)
            ~contains_non_zero:(Ival.Float_abstract.maybe_le_ieee_float f1 f2)
      | Gt ->
          V.interp_boolean
            ~contains_zero:(Ival.Float_abstract.maybe_le_ieee_float f1 f2)
            ~contains_non_zero:(Ival.Float_abstract.maybe_lt_ieee_float f2 f1)
      | Ge ->
          V.interp_boolean
            ~contains_zero:(Ival.Float_abstract.maybe_lt_ieee_float f1 f2)
            ~contains_non_zero:(Ival.Float_abstract.maybe_le_ieee_float f2 f1)
      | _ -> raise V.Not_based_on_null
    end
  with V.Not_based_on_null | Ival.F.Nan_or_infinite ->
    warning_once_current
      "float operation on address.";
    V.join
      (V.topify_arith_origin ev1)
      (V.topify_arith_origin ev2)