bool simplify_exprt::simplify_sign(exprt &expr)
{
  if(expr.operands().size()!=1) return true;

  if(expr.op0().is_constant())
  {
    const typet &type=ns.follow(expr.op0().type());

    if(type.id()==ID_floatbv)
    {
      ieee_floatt value(to_constant_expr(expr.op0()));
      expr.make_bool(value.get_sign());
      return false;
    }
    else if(type.id()==ID_signedbv ||
            type.id()==ID_unsignedbv)
    {
      mp_integer value;
      if(!to_integer(expr.op0(), value))
      {
        expr.make_bool(value>=0);
        return false;
      }
    }
  }

  return true;
}
bool simplify_exprt::simplify_ieee_float_relation(exprt &expr)
{
  assert(expr.id()==ID_ieee_float_equal ||
         expr.id()==ID_ieee_float_notequal);

  exprt::operandst &operands=expr.operands();

  if(expr.type().id()!=ID_bool)
    return true;

  if(operands.size()!=2)
    return true;

  // types must match
  if(expr.op0().type()!=expr.op1().type())
    return true;

  if(expr.op0().type().id()!=ID_floatbv)
    return true;

  // first see if we compare to a constant

  if(expr.op0().is_constant() &&
     expr.op1().is_constant())
  {
    ieee_floatt f0(to_constant_expr(expr.op0()));
    ieee_floatt f1(to_constant_expr(expr.op1()));

    if(expr.id()==ID_ieee_float_notequal)
      expr.make_bool(f0.ieee_not_equal(f1));
    else if(expr.id()==ID_ieee_float_equal)
      expr.make_bool(f0.ieee_equal(f1));
    else
      assert(false);

    return false;
  }

  if(expr.op0()==expr.op1())
  {
    // x!=x is the same as saying isnan(op)
    exprt isnan(ID_isnan, bool_typet());
    isnan.copy_to_operands(expr.op0());

    if(expr.id()==ID_ieee_float_notequal)
    {
    }
    else if(expr.id()==ID_ieee_float_equal)
      isnan.make_not();
    else
      assert(false);

    expr.swap(isnan);
    return false;
  }

  return true;
}
bool simplify_exprt::simplify_isnormal(exprt &expr)
{
  if(expr.operands().size()!=1) return true;

  if(expr.op0().is_constant())
  {
    ieee_floatt value(to_constant_expr(expr.op0()));
    expr.make_bool(value.is_normal());
    return false;
  }

  return true;
}
bool simplify_exprt::simplify_isinf(exprt &expr)
{
  if(expr.operands().size()!=1) return true;

  if(ns.follow(expr.op0().type()).id()!=ID_floatbv)
    return true;

  if(expr.op0().is_constant())
  {
    ieee_floatt value(to_constant_expr(expr.op0()));
    expr.make_bool(value.is_infinity());
    return false;
  }

  return true;
}
bool simplify_exprt::simplify_inequality_address_of(exprt &expr)
{
    assert(expr.type().id()==ID_bool);
    assert(expr.operands().size()==2);
    assert(expr.id()==ID_equal || expr.id()==ID_notequal);

    exprt tmp0=expr.op0();
    if(tmp0.id()==ID_typecast)
        tmp0=expr.op0().op0();
    if(tmp0.op0().id()==ID_index &&
            to_index_expr(tmp0.op0()).index().is_zero())
        tmp0=address_of_exprt(to_index_expr(tmp0.op0()).array());
    exprt tmp1=expr.op1();
    if(tmp1.id()==ID_typecast)
        tmp1=expr.op1().op0();
    if(tmp1.op0().id()==ID_index &&
            to_index_expr(tmp1.op0()).index().is_zero())
        tmp1=address_of_exprt(to_index_expr(tmp1.op0()).array());
    assert(tmp0.id()==ID_address_of);
    assert(tmp1.id()==ID_address_of);

    if(tmp0.operands().size()!=1) return true;
    if(tmp1.operands().size()!=1) return true;

    if(tmp0.op0().id()==ID_symbol &&
            tmp1.op0().id()==ID_symbol)
    {
        bool equal=
            tmp0.op0().get(ID_identifier)==
            tmp1.op0().get(ID_identifier);

        expr.make_bool(expr.id()==ID_equal?equal:!equal);

        return false;
    }

    return true;
}