LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/arith - arith_rewriter.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 844 901 93.7 %
Date: 2026-07-28 10:35:35 Functions: 36 37 97.3 %
Branches: 614 918 66.9 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * [[ Add one-line brief description here ]]
      11                 :            :  *
      12                 :            :  * [[ Add lengthier description here ]]
      13                 :            :  * \todo document this file
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "theory/arith/arith_rewriter.h"
      17                 :            : 
      18                 :            : #include <optional>
      19                 :            : #include <set>
      20                 :            : #include <sstream>
      21                 :            : #include <stack>
      22                 :            : #include <vector>
      23                 :            : 
      24                 :            : #include "expr/algorithm/flatten.h"
      25                 :            : #include "expr/node_algorithm.h"
      26                 :            : #include "smt/logic_exception.h"
      27                 :            : #include "theory/arith/arith_msum.h"
      28                 :            : #include "theory/arith/arith_utilities.h"
      29                 :            : #include "theory/arith/operator_elim.h"
      30                 :            : #include "theory/arith/rewriter/addition.h"
      31                 :            : #include "theory/arith/rewriter/node_utils.h"
      32                 :            : #include "theory/arith/rewriter/ordering.h"
      33                 :            : #include "theory/arith/rewriter/rewrite_atom.h"
      34                 :            : #include "theory/evaluator.h"
      35                 :            : #include "theory/rewriter.h"
      36                 :            : #include "theory/strings/arith_entail.h"
      37                 :            : #include "theory/theory.h"
      38                 :            : #include "util/bitvector.h"
      39                 :            : #include "util/divisible.h"
      40                 :            : #include "util/iand.h"
      41                 :            : #include "util/real_algebraic_number.h"
      42                 :            : 
      43                 :            : using namespace cvc5::internal::kind;
      44                 :            : 
      45                 :            : namespace cvc5::internal {
      46                 :            : namespace theory {
      47                 :            : namespace arith {
      48                 :            : 
      49                 :            : /**
      50                 :            :  * Flatten a node into a vector of its (direct or indirect) children, collecting
      51                 :            :  * how many times each child occurs in the sum.
      52                 :            :  * A sequence of kinds is given that indicate which kinds to traverse over.
      53                 :            :  * This method is similar to expr::algorithm::flatten but does not use a tree
      54                 :            :  * traversal. Instead it merges subterms, based on counting the number of
      55                 :            :  * occurrences, as a Rational.
      56                 :            :  * @param t The node to be flattened
      57                 :            :  * @param children The resulting list of children
      58                 :            :  * @param kinds A sequence of kinds to consider for flattening
      59                 :            :  */
      60                 :            : template <typename... Kinds>
      61                 :    5402135 : bool flattenAndCollectSum(TNode t,
      62                 :            :                           std::vector<std::pair<TNode, Rational>>& children,
      63                 :            :                           Kinds... kinds)
      64                 :            : {
      65         [ +  + ]:    5402135 :   if (!expr::algorithm::canFlatten(t, kinds...))
      66                 :            :   {
      67                 :    4891519 :     return false;
      68                 :            :   }
      69                 :            :   // Note we use an *ordered* map, where we assume that nodes are ordered by
      70                 :            :   // their id, where nodes constructed later have a larger id. This ensures
      71                 :            :   // we process nodes in the (reverse) order in which they constructed, newest
      72                 :            :   // nodes processed first, thus ensuring we process each node only once while
      73                 :            :   // flattening.
      74                 :     510616 :   std::map<TNode, Rational> countMap;
      75                 :     510616 :   countMap[t] = Rational(1);
      76                 :     510616 :   std::map<TNode, Rational>::iterator it;
      77                 :     510616 :   Kind tk = t.getKind();
      78         [ +  + ]:    7353120 :   while (!countMap.empty())
      79                 :            :   {
      80                 :            :     // Go off of end first. This is important for efficiency since later terms
      81                 :            :     // in the map may contain subterms that are earlier terms in the map.
      82                 :    3421252 :     std::map<TNode, Rational>::iterator cur = std::prev(countMap.end());
      83                 :    3421252 :     bool recurse = false;
      84                 :    3421252 :     TNode tc = cur->first;
      85                 :    3421252 :     Kind k = tc.getKind();
      86                 :    3421252 :     Rational coeff = cur->second;
      87                 :    3421252 :     countMap.erase(cur);
      88                 :            :     // Additionally collect coefficient
      89 [ +  + ][ +  - ]:    4296184 :     while (k == Kind::MULT && tc.getNumChildren() == 2 && tc[0].isConst())
         [ +  + ][ +  + ]
         [ +  + ][ -  - ]
      90                 :            :     {
      91                 :     874932 :       coeff *= tc[0].getConst<Rational>();
      92                 :     874932 :       tc = tc[1];
      93                 :     874932 :       k = tc.getKind();
      94                 :            :     }
      95                 :            :     // figure out whether to recurse into cur
      96                 :            :     if constexpr (sizeof...(kinds) == 0)
      97                 :            :     {
      98                 :            :       recurse = tk == k;
      99                 :            :     }
     100                 :            :     else
     101                 :            :     {
     102 [ +  + ][ +  + ]:    3421252 :       recurse = ((kinds == k) || ...);
     103                 :            :     }
     104         [ +  + ]:    3421252 :     if (recurse)
     105                 :            :     {
     106         [ +  + ]:    6309258 :       for (TNode cc : tc)
     107                 :            :       {
     108                 :    3320336 :         countMap[cc] += coeff;
     109                 :            :       }
     110                 :            :     }
     111                 :            :     else
     112                 :            :     {
     113                 :    1926791 :       children.emplace_back(tc, coeff);
     114                 :            :     }
     115                 :            :   }
     116                 :     510616 :   return true;
     117                 :     510616 : }
     118                 :            : 
     119                 :      28698 : ArithRewriter::ArithRewriter(NodeManager* nm,
     120                 :            :                              OperatorElim& oe,
     121                 :      28698 :                              bool expertEnabled)
     122                 :      28698 :     : TheoryRewriter(nm), d_opElim(oe), d_expertEnabled(expertEnabled)
     123                 :            : {
     124                 :      28698 :   registerProofRewriteRule(ProofRewriteRule::ARITH_POW_ELIM,
     125                 :            :                            TheoryRewriteCtx::PRE_DSL);
     126                 :      28698 :   registerProofRewriteRule(ProofRewriteRule::MACRO_ARITH_STRING_PRED_ENTAIL,
     127                 :            :                            TheoryRewriteCtx::DSL_SUBCALL);
     128                 :      28698 :   registerProofRewriteRule(ProofRewriteRule::MACRO_ARITH_INT_EQ_CONFLICT,
     129                 :            :                            TheoryRewriteCtx::DSL_SUBCALL);
     130                 :      28698 :   registerProofRewriteRule(ProofRewriteRule::MACRO_ARITH_INT_GEQ_TIGHTEN,
     131                 :            :                            TheoryRewriteCtx::DSL_SUBCALL);
     132                 :            :   // we don't register ARITH_STRING_PRED_ENTAIL or
     133                 :            :   // ARITH_STRING_PRED_SAFE_APPROX, as these are subsumed by
     134                 :            :   // MACRO_ARITH_STRING_PRED_ENTAIL.
     135                 :      28698 : }
     136                 :            : 
     137                 :    2035267 : Node ArithRewriter::rewriteViaRule(ProofRewriteRule id, const Node& n)
     138                 :            : {
     139 [ +  + ][ +  + ]:    2035267 :   switch (id)
                 [ +  + ]
     140                 :            :   {
     141                 :     223210 :     case ProofRewriteRule::ARITH_POW_ELIM:
     142                 :            :     {
     143         [ +  + ]:     223210 :       if (n.getKind() == Kind::POW)
     144                 :            :       {
     145                 :          7 :         Node nx = expandPowConst(nodeManager(), n);
     146         [ +  - ]:          7 :         if (!nx.isNull())
     147                 :            :         {
     148                 :          7 :           return nx;
     149                 :            :         }
     150         [ -  + ]:          7 :       }
     151                 :            :     }
     152                 :     223203 :     break;
     153                 :     605270 :     case ProofRewriteRule::MACRO_ARITH_STRING_PRED_ENTAIL:
     154                 :            :     {
     155                 :            :       // only matters if n contains integer string operators
     156                 :    1120114 :       if (!n.getType().isBoolean() || n.getNumChildren() != 2 || n[0] == n[1]
     157                 :    1120114 :           || !expr::hasSubtermKinds(
     158                 :            :               {Kind::STRING_LENGTH, Kind::STRING_INDEXOF, Kind::STRING_STOI},
     159                 :            :               n))
     160                 :            :       {
     161                 :     487140 :         return Node::null();
     162                 :            :       }
     163         [ +  - ]:     118130 :       Trace("macro-arith-str-pred") << "Check entailment " << n << std::endl;
     164                 :            :       // Note that we do *not* pass a rewriter here, since the proof rule
     165                 :            :       // cannot depend on the rewriter. This makes this rule capture most
     166                 :            :       // but not all cases of this kind of reasoning.
     167                 :     118130 :       theory::strings::ArithEntail ae(d_nm, nullptr);
     168                 :     118130 :       Node tgt;
     169         [ +  + ]:     118130 :       if (n.getKind() == Kind::EQUAL)
     170                 :            :       {
     171                 :      21932 :         tgt = n;
     172                 :            :       }
     173                 :            :       else
     174                 :            :       {
     175                 :      96198 :         tgt = ae.normalizeGeq(n);
     176                 :            :       }
     177                 :     118130 :       if (tgt.isNull() || !tgt[0].getType().isInteger())
     178                 :            :       {
     179                 :         93 :         return Node::null();
     180                 :            :       }
     181                 :            :       // first do basic length intro, which rewrites (str.len (str.++ x y))
     182                 :            :       // to (+ (str.len x) (str.len y))
     183                 :     118037 :       Node nexp = ae.rewriteLengthIntro(tgt);
     184         [ +  - ]:     118037 :       Trace("macro-arith-str-pred") << "...setup to " << nexp << std::endl;
     185                 :            :       // Also must make this a "simple" check (isSimple = true).
     186                 :     118037 :       Node ret = ae.rewritePredViaEntailment(nexp, true);
     187         [ +  - ]:     118037 :       Trace("macro-arith-str-pred") << "...result = " << ret << std::endl;
     188                 :     118037 :       return ret;
     189                 :     118130 :     }
     190                 :            :     break;
     191                 :        215 :     case ProofRewriteRule::ARITH_STRING_PRED_ENTAIL:
     192                 :            :     case ProofRewriteRule::ARITH_STRING_PRED_SAFE_APPROX:
     193                 :            :     {
     194 [ +  - ][ -  + ]:        430 :       if (n.getKind() != Kind::GEQ || !n[1].isConst()
                 [ -  - ]
     195 [ +  - ][ -  + ]:        430 :           || n[1].getConst<Rational>().sgn() != 0)
         [ +  - ][ +  - ]
                 [ -  - ]
     196                 :            :       {
     197                 :          0 :         return Node::null();
     198                 :            :       }
     199         [ +  + ]:        215 :       if (id == ProofRewriteRule::ARITH_STRING_PRED_ENTAIL)
     200                 :            :       {
     201         [ +  - ]:        138 :         if (theory::strings::ArithEntail::checkSimple(n[0]))
     202                 :            :         {
     203                 :        276 :           return nodeManager()->mkConst(true);
     204                 :            :         }
     205                 :            :       }
     206         [ +  - ]:         77 :       else if (id == ProofRewriteRule::ARITH_STRING_PRED_SAFE_APPROX)
     207                 :            :       {
     208                 :            :         // Note that we do *not* pass a rewriter here, since the proof rule
     209                 :            :         // cannot depend on the rewriter.
     210                 :         77 :         theory::strings::ArithEntail ae(nodeManager(), nullptr);
     211                 :            :         // must only use simple checks when computing the approximations
     212                 :         77 :         Node approx = ae.findApprox(n[0], true);
     213         [ +  - ]:         77 :         if (approx != n[0])
     214                 :            :         {
     215         [ +  - ]:        154 :           Trace("arith-rewriter-proof")
     216 [ -  + ][ -  - ]:         77 :               << n[0] << " --> " << approx << " by safe approx" << std::endl;
     217                 :         77 :           return nodeManager()->mkNode(Kind::GEQ, approx, n[1]);
     218                 :            :         }
     219 [ -  + ][ -  + ]:        154 :       }
     220                 :            :     }
     221                 :          0 :     break;
     222                 :     603334 :     case ProofRewriteRule::MACRO_ARITH_INT_EQ_CONFLICT:
     223                 :            :     {
     224                 :     603334 :       if (n.getKind() == Kind::EQUAL && n[0] != n[1])
     225                 :            :       {
     226 [ +  + ][ +  + ]:     100317 :         Node a = n[0].getKind() == Kind::TO_REAL ? n[0][0] : n[0];
                 [ -  - ]
     227 [ +  + ][ +  + ]:     100222 :         Node b = n[1].getKind() == Kind::TO_REAL ? n[1][0] : n[1];
                 [ -  - ]
     228                 :      99956 :         rewriter::Sum sum;
     229                 :            :         // allow dropping TO_REAL
     230                 :      99956 :         rewriter::addToSumNoMixed(sum, a, false);
     231                 :      99956 :         rewriter::addToSumNoMixed(sum, b, true);
     232         [ +  + ]:      99956 :         if (rewriter::isIntegral(sum))
     233                 :            :         {
     234                 :      77487 :           std::pair<Node, Node> p = decomposeSum(d_nm, std::move(sum));
     235                 :      77487 :           Rational c = p.second.getConst<Rational>();
     236         [ +  + ]:      77487 :           if (!c.isIntegral())
     237                 :            :           {
     238                 :        336 :             return d_nm->mkConst(false);
     239                 :            :           }
     240 [ +  + ][ +  + ]:      77655 :         }
     241 [ +  + ][ +  + ]:     100292 :       }
                 [ +  + ]
     242                 :            :     }
     243                 :     603166 :     break;
     244                 :     603233 :     case ProofRewriteRule::MACRO_ARITH_INT_GEQ_TIGHTEN:
     245                 :            :     {
     246         [ +  - ]:     603233 :       Trace("arith-rewriter-proof") << "Rewrite " << n << "?" << std::endl;
     247                 :     603233 :       if (n.getKind() == Kind::GEQ && n[0] != n[1])
     248                 :            :       {
     249 [ +  + ][ +  + ]:     206129 :         Node a = n[0].getKind() == Kind::TO_REAL ? n[0][0] : n[0];
                 [ -  - ]
     250 [ +  + ][ +  + ]:     206090 :         Node b = n[1].getKind() == Kind::TO_REAL ? n[1][0] : n[1];
                 [ -  - ]
     251                 :     205869 :         rewriter::Sum sum;
     252                 :            :         // allow dropping TO_REAL
     253                 :     205869 :         rewriter::addToSumNoMixed(sum, a, false);
     254                 :     205869 :         rewriter::addToSumNoMixed(sum, b, true);
     255         [ +  + ]:     205869 :         if (rewriter::isIntegral(sum))
     256                 :            :         {
     257                 :            :           // decompose the sum into a non-constant and constant part
     258                 :     168542 :           bool negated = false;
     259                 :            :           std::pair<Node, Node> p =
     260                 :     168542 :               decomposeSum(d_nm, std::move(sum), negated, true);
     261                 :     168542 :           Rational c = p.second.getConst<Rational>();
     262         [ +  - ]:     337084 :           Trace("arith-rewriter-proof")
     263                 :     168542 :               << "Decomposed to " << p.first << " + " << p.second << std::endl;
     264         [ +  + ]:     168542 :           if (!c.isIntegral())
     265                 :            :           {
     266                 :        180 :             c = -c;
     267                 :        180 :             c = c.ceiling();
     268                 :        360 :             Node ret = d_nm->mkNode(Kind::GEQ, p.first, d_nm->mkConstInt(c));
     269         [ +  + ]:        180 :             if (negated)
     270                 :            :             {
     271                 :         83 :               ret = ret.notNode();
     272                 :            :             }
     273                 :        180 :             return ret;
     274                 :        180 :           }
     275 [ +  + ][ +  + ]:     168722 :         }
     276 [ +  + ][ +  + ]:     206229 :       }
                 [ +  + ]
     277                 :            :     }
     278                 :     603053 :     break;
     279                 :          5 :     default: break;
     280                 :            :   }
     281                 :    1429427 :   return Node::null();
     282                 :            : }
     283                 :            : 
     284                 :   12702724 : RewriteResponse ArithRewriter::preRewrite(TNode t)
     285                 :            : {
     286         [ +  - ]:   12702724 :   Trace("arith-rewriter") << "preRewrite(" << t << ")" << std::endl;
     287         [ +  + ]:   12702724 :   if (rewriter::isAtom(t))
     288                 :            :   {
     289                 :    6769978 :     auto res = preRewriteAtom(t);
     290         [ +  - ]:   13539956 :     Trace("arith-rewriter")
     291                 :    6769978 :         << res.d_status << " -> " << res.d_node << std::endl;
     292                 :    6769978 :     return res;
     293                 :    6769978 :   }
     294                 :    5932746 :   auto res = preRewriteTerm(t);
     295         [ +  - ]:    5932746 :   Trace("arith-rewriter") << res.d_status << " -> " << res.d_node << std::endl;
     296                 :    5932746 :   return res;
     297                 :    5932746 : }
     298                 :            : 
     299                 :   10876384 : RewriteResponse ArithRewriter::postRewrite(TNode t)
     300                 :            : {
     301         [ +  - ]:   10876384 :   Trace("arith-rewriter") << "postRewrite(" << t << ")" << std::endl;
     302         [ +  + ]:   10876384 :   if (rewriter::isAtom(t))
     303                 :            :   {
     304                 :    5689389 :     auto res = postRewriteAtom(t);
     305         [ +  - ]:   11378778 :     Trace("arith-rewriter")
     306                 :    5689389 :         << res.d_status << " -> " << res.d_node << std::endl;
     307                 :    5689389 :     return res;
     308                 :    5689389 :   }
     309                 :    5186995 :   auto res = postRewriteTerm(t);
     310         [ +  - ]:    5186995 :   Trace("arith-rewriter") << res.d_status << " -> " << res.d_node << std::endl;
     311                 :    5186995 :   return res;
     312                 :    5186995 : }
     313                 :            : 
     314                 :    6769978 : RewriteResponse ArithRewriter::preRewriteAtom(TNode atom)
     315                 :            : {
     316 [ -  + ][ -  + ]:    6769978 :   Assert(rewriter::isAtom(atom));
                 [ -  - ]
     317                 :            : 
     318                 :    6769978 :   Kind kind = atom.getKind();
     319         [ +  + ]:    6769978 :   if (atom.getNumChildren() == 2)
     320                 :            :   {
     321         [ +  + ]:    6769023 :     if (auto response =
     322                 :    6769023 :             rewriter::tryEvaluateRelationReflexive(kind, atom[0], atom[1]);
     323                 :    6769023 :         response)
     324                 :            :     {
     325                 :     197124 :       return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, *response));
     326                 :            :     }
     327                 :            :   }
     328                 :            : 
     329 [ +  + ][ +  + ]:    6671416 :   switch (kind)
                    [ + ]
     330                 :            :   {
     331                 :     245058 :     case Kind::GT:
     332                 :            :       return RewriteResponse(
     333                 :            :           REWRITE_DONE,
     334                 :     490116 :           rewriter::buildRelation(Kind::LEQ, atom[0], atom[1], true));
     335                 :     218803 :     case Kind::LT:
     336                 :            :       return RewriteResponse(
     337                 :            :           REWRITE_DONE,
     338                 :     437606 :           rewriter::buildRelation(Kind::GEQ, atom[0], atom[1], true));
     339                 :        877 :     case Kind::IS_INTEGER:
     340         [ +  + ]:        877 :       if (atom[0].getType().isInteger())
     341                 :            :       {
     342                 :         10 :         return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, true));
     343                 :            :       }
     344                 :        872 :       break;
     345                 :         78 :     case Kind::DIVISIBLE:
     346         [ -  + ]:         78 :       if (atom.getOperator().getConst<Divisible>().k.isOne())
     347                 :            :       {
     348                 :          0 :         return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, true));
     349                 :            :       }
     350                 :         78 :       break;
     351                 :    6207550 :     default:;
     352                 :            :   }
     353                 :            : 
     354                 :    6207550 :   return RewriteResponse(REWRITE_DONE, atom);
     355                 :            : }
     356                 :            : 
     357                 :    5689389 : RewriteResponse ArithRewriter::postRewriteAtom(TNode atom)
     358                 :            : {
     359 [ -  + ][ -  + ]:    5689389 :   Assert(rewriter::isAtom(atom));
                 [ -  - ]
     360         [ +  - ]:    5689389 :   Trace("arith-rewriter") << "postRewriteAtom: " << atom << std::endl;
     361                 :            : 
     362         [ +  + ]:    5689389 :   if (atom.getKind() == Kind::IS_INTEGER)
     363                 :            :   {
     364                 :        838 :     return rewriteExtIntegerOp(atom);
     365                 :            :   }
     366         [ +  + ]:    5688551 :   else if (atom.getKind() == Kind::DIVISIBLE)
     367                 :            :   {
     368                 :         39 :     const Integer& k = atom.getOperator().getConst<Divisible>().k;
     369         [ -  + ]:         39 :     if (atom[0].isConst())
     370                 :            :     {
     371                 :          0 :       const Rational& num = atom[0].getConst<Rational>();
     372                 :            :       return RewriteResponse(REWRITE_DONE,
     373                 :          0 :                              rewriter::mkConst(d_nm, (num / k).isIntegral()));
     374                 :            :     }
     375         [ -  + ]:         39 :     if (k.isOne())
     376                 :            :     {
     377                 :          0 :       return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, true));
     378                 :            :     }
     379                 :         39 :     NodeManager* nm = nodeManager();
     380                 :            :     return RewriteResponse(REWRITE_AGAIN_FULL,
     381 [ +  + ][ -  - ]:        195 :                            nm->mkNode(Kind::EQUAL,
     382                 :         78 :                                       {nm->mkNode(Kind::INTS_MODULUS_TOTAL,
     383                 :            :                                                   atom[0],
     384                 :         78 :                                                   rewriter::mkConst(d_nm, k)),
     385                 :        117 :                                        rewriter::mkConst(d_nm, Integer(0))}));
     386                 :            :   }
     387                 :            :   // left |><| right
     388                 :    5688512 :   Kind kind = atom.getKind();
     389                 :   11377024 :   Node left = rewriter::removeToReal(atom[0]);
     390                 :   11377024 :   Node right = rewriter::removeToReal(atom[1]);
     391                 :            : 
     392         [ +  + ]:   11377024 :   if (auto response = rewriter::tryEvaluateRelationReflexive(kind, left, right);
     393                 :    5688512 :       response)
     394                 :            :   {
     395                 :     347576 :     return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, *response));
     396                 :            :   }
     397                 :            : 
     398 [ -  + ][ -  + ]:    5514724 :   Assert(isRelationOperator(kind));
                 [ -  - ]
     399                 :            : 
     400         [ +  + ]:   11029448 :   if (auto response = rewriter::tryEvaluateRelation(kind, left, right);
     401                 :    5514724 :       response)
     402                 :            :   {
     403                 :    1087572 :     return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, *response));
     404                 :            :   }
     405                 :            : 
     406                 :    4970938 :   bool negate = false;
     407                 :            : 
     408    [ +  - ][ + ]:    4970938 :   switch (atom.getKind())
     409                 :            :   {
     410                 :     304898 :     case Kind::LEQ:
     411                 :     304898 :       kind = Kind::GEQ;
     412                 :     304898 :       negate = true;
     413                 :     304898 :       break;
     414                 :          0 :     case Kind::LT:
     415                 :          0 :       kind = Kind::GT;
     416                 :          0 :       negate = true;
     417                 :          0 :       break;
     418                 :    4666040 :     default: break;
     419                 :            :   }
     420                 :            : 
     421                 :    9941876 :   rewriter::Sum sum;
     422                 :    4970938 :   rewriter::addToSum(sum, left, negate);
     423                 :    4970938 :   rewriter::addToSum(sum, right, !negate);
     424                 :            : 
     425                 :            :   // Now we have (sum <kind> 0)
     426         [ +  + ]:    4970938 :   if (rewriter::isIntegral(sum))
     427                 :            :   {
     428         [ +  - ]:    3720139 :     Trace("arith-rewriter") << "...sum is integral" << std::endl;
     429         [ +  + ]:    3720139 :     if (kind == Kind::EQUAL)
     430                 :            :     {
     431                 :            :       return RewriteResponse(
     432                 :    3820854 :           REWRITE_DONE, rewriter::buildIntegerEquality(d_nm, std::move(sum)));
     433                 :            :     }
     434                 :            :     return RewriteResponse(
     435                 :            :         REWRITE_DONE,
     436                 :    3619424 :         rewriter::buildIntegerInequality(d_nm, std::move(sum), kind));
     437                 :            :   }
     438                 :            :   else
     439                 :            :   {
     440         [ +  - ]:    1250799 :     Trace("arith-rewriter") << "...sum is not integral" << std::endl;
     441         [ +  + ]:    1250799 :     if (kind == Kind::EQUAL)
     442                 :            :     {
     443                 :            :       return RewriteResponse(REWRITE_DONE,
     444                 :     610622 :                              rewriter::buildRealEquality(d_nm, std::move(sum)));
     445                 :            :     }
     446                 :            :     return RewriteResponse(
     447                 :            :         REWRITE_DONE,
     448                 :    1890976 :         rewriter::buildRealInequality(d_nm, std::move(sum), kind));
     449                 :            :   }
     450                 :    5688512 : }
     451                 :            : 
     452                 :    5932746 : RewriteResponse ArithRewriter::preRewriteTerm(TNode t)
     453                 :            : {
     454         [ +  + ]:    5932746 :   if (t.isConst())
     455                 :            :   {
     456                 :     794962 :     return RewriteResponse(REWRITE_DONE, t);
     457                 :            :   }
     458         [ -  + ]:    5137784 :   else if (t.isVar())
     459                 :            :   {
     460                 :          0 :     return rewriteVariable(t);
     461                 :            :   }
     462                 :            :   else
     463                 :            :   {
     464 [ +  + ][ +  + ]:    5137784 :     switch (Kind k = t.getKind())
         [ +  + ][ +  + ]
            [ +  + ][ - ]
     465                 :            :     {
     466                 :        274 :       case Kind::REAL_ALGEBRAIC_NUMBER: return rewriteRAN(t);
     467                 :     557726 :       case Kind::SUB: return rewriteSub(t);
     468                 :      23556 :       case Kind::NEG: return rewriteNeg(t, true);
     469                 :      10937 :       case Kind::DIVISION:
     470                 :      10937 :       case Kind::DIVISION_TOTAL: return rewriteDiv(t, true);
     471                 :    3155228 :       case Kind::ADD: return preRewritePlus(t);
     472                 :    1312179 :       case Kind::MULT:
     473                 :    1312179 :       case Kind::NONLINEAR_MULT: return preRewriteMult(t);
     474                 :       8432 :       case Kind::INTS_DIVISION:
     475                 :       8432 :       case Kind::INTS_MODULUS: return rewriteIntsDivMod(t);
     476                 :      25908 :       case Kind::INTS_DIVISION_TOTAL:
     477                 :      25908 :       case Kind::INTS_MODULUS_TOTAL: return rewriteIntsDivModTotal(t, true);
     478                 :       6604 :       case Kind::ABS: return rewriteAbs(t);
     479                 :      36940 :       case Kind::IAND:
     480                 :            :       case Kind::PIAND:
     481                 :            :       case Kind::POW2:
     482                 :            :       case Kind::INTS_ISPOW2:
     483                 :            :       case Kind::INTS_LOG2:
     484                 :            :       case Kind::EXPONENTIAL:
     485                 :            :       case Kind::SINE:
     486                 :            :       case Kind::COSINE:
     487                 :            :       case Kind::TANGENT:
     488                 :            :       case Kind::COSECANT:
     489                 :            :       case Kind::SECANT:
     490                 :            :       case Kind::COTANGENT:
     491                 :            :       case Kind::ARCSINE:
     492                 :            :       case Kind::ARCCOSINE:
     493                 :            :       case Kind::ARCTANGENT:
     494                 :            :       case Kind::ARCCOSECANT:
     495                 :            :       case Kind::ARCSECANT:
     496                 :            :       case Kind::ARCCOTANGENT:
     497                 :            :       case Kind::SQRT:
     498                 :            :       case Kind::IS_INTEGER:
     499                 :            :       case Kind::TO_INTEGER:
     500                 :            :       case Kind::TO_REAL:
     501                 :            :       case Kind::POW:
     502                 :      36940 :       case Kind::PI: return RewriteResponse(REWRITE_DONE, t);
     503                 :          0 :       default: Unhandled() << k;
     504                 :            :     }
     505                 :            :   }
     506                 :            : }
     507                 :            : 
     508                 :    5186995 : RewriteResponse ArithRewriter::postRewriteTerm(TNode t)
     509                 :            : {
     510         [ +  + ]:    5186995 :   if (t.isConst())
     511                 :            :   {
     512                 :    1780221 :     return RewriteResponse(REWRITE_DONE, t);
     513                 :            :   }
     514         [ -  + ]:    3406774 :   else if (t.isVar())
     515                 :            :   {
     516                 :          0 :     return rewriteVariable(t);
     517                 :            :   }
     518                 :            :   else
     519                 :            :   {
     520         [ +  - ]:    3406774 :     Trace("arith-rewriter") << "postRewriteTerm: " << t << std::endl;
     521 [ +  - ][ -  + ]:    3406774 :     switch (t.getKind())
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  - ]
     522                 :            :     {
     523                 :        397 :       case Kind::REAL_ALGEBRAIC_NUMBER: return rewriteRAN(t);
     524                 :          0 :       case Kind::SUB: return rewriteSub(t);
     525                 :          0 :       case Kind::NEG: return rewriteNeg(t, false);
     526                 :       5492 :       case Kind::DIVISION:
     527                 :       5492 :       case Kind::DIVISION_TOTAL: return rewriteDiv(t, false);
     528                 :    2246907 :       case Kind::ADD: return postRewritePlus(t);
     529                 :    1080012 :       case Kind::MULT:
     530                 :    1080012 :       case Kind::NONLINEAR_MULT: return postRewriteMult(t);
     531                 :        142 :       case Kind::INTS_ISPOW2: return postRewriteIntsIsPow2(t);
     532                 :        215 :       case Kind::INTS_LOG2: return postRewriteIntsLog2(t);
     533                 :       6620 :       case Kind::INTS_DIVISION:
     534                 :       6620 :       case Kind::INTS_MODULUS: return rewriteIntsDivMod(t);
     535                 :      20477 :       case Kind::INTS_DIVISION_TOTAL:
     536                 :      20477 :       case Kind::INTS_MODULUS_TOTAL: return rewriteIntsDivModTotal(t, false);
     537                 :       6266 :       case Kind::ABS: return rewriteAbs(t);
     538                 :      23058 :       case Kind::TO_REAL: return rewriteToReal(t);
     539                 :       3477 :       case Kind::TO_INTEGER: return rewriteExtIntegerOp(t);
     540                 :        888 :       case Kind::PI: return RewriteResponse(REWRITE_DONE, t);
     541                 :       1949 :       case Kind::POW2: return postRewritePow2(t);
     542                 :        775 :       case Kind::PIAND: return postRewritePIAnd(t);
     543                 :            :       // expert cases
     544                 :      10099 :       case Kind::POW:
     545                 :            :       case Kind::EXPONENTIAL:
     546                 :            :       case Kind::SINE:
     547                 :            :       case Kind::COSINE:
     548                 :            :       case Kind::TANGENT:
     549                 :            :       case Kind::COSECANT:
     550                 :            :       case Kind::SECANT:
     551                 :            :       case Kind::COTANGENT:
     552                 :            :       case Kind::ARCSINE:
     553                 :            :       case Kind::ARCCOSINE:
     554                 :            :       case Kind::ARCTANGENT:
     555                 :            :       case Kind::ARCCOSECANT:
     556                 :            :       case Kind::ARCSECANT:
     557                 :            :       case Kind::ARCCOTANGENT:
     558                 :            :       case Kind::SQRT:
     559                 :      10099 :       case Kind::IAND: return postRewriteExpert(t);
     560                 :          0 :       default: Unreachable();
     561                 :            :     }
     562                 :            :   }
     563                 :            : }
     564                 :      10099 : RewriteResponse ArithRewriter::postRewriteExpert(TNode t)
     565                 :            : {
     566         [ -  + ]:      10099 :   if (!d_expertEnabled)
     567                 :            :   {
     568                 :          0 :     return RewriteResponse(REWRITE_DONE, t);
     569                 :            :   }
     570 [ +  + ][ +  - ]:      10099 :   switch (t.getKind())
     571                 :            :   {
     572                 :        214 :     case Kind::POW:
     573                 :            :     {
     574                 :        214 :       Node tx = expandPowConst(nodeManager(), t);
     575         [ +  + ]:        214 :       if (!tx.isNull())
     576                 :            :       {
     577                 :        202 :         return RewriteResponse(REWRITE_AGAIN_FULL, tx);
     578                 :            :       }
     579                 :         12 :       return RewriteResponse(REWRITE_DONE, t);
     580                 :        214 :     }
     581                 :       7881 :     case Kind::EXPONENTIAL:
     582                 :            :     case Kind::SINE:
     583                 :            :     case Kind::COSINE:
     584                 :            :     case Kind::TANGENT:
     585                 :            :     case Kind::COSECANT:
     586                 :            :     case Kind::SECANT:
     587                 :            :     case Kind::COTANGENT:
     588                 :            :     case Kind::ARCSINE:
     589                 :            :     case Kind::ARCCOSINE:
     590                 :            :     case Kind::ARCTANGENT:
     591                 :            :     case Kind::ARCCOSECANT:
     592                 :            :     case Kind::ARCSECANT:
     593                 :            :     case Kind::ARCCOTANGENT:
     594                 :       7881 :     case Kind::SQRT: return postRewriteTranscendental(t);
     595                 :       2004 :     case Kind::IAND: return postRewriteIAnd(t);
     596                 :          0 :     default: Unreachable();
     597                 :            :   }
     598                 :            : }
     599                 :            : 
     600                 :        671 : RewriteResponse ArithRewriter::rewriteRAN(TNode t)
     601                 :            : {
     602 [ -  + ][ -  + ]:        671 :   Assert(rewriter::isRAN(t));
                 [ -  - ]
     603 [ -  + ][ -  + ]:        671 :   Assert(t.getType().isReal());
                 [ -  - ]
     604                 :        671 :   const RealAlgebraicNumber& r = rewriter::getRAN(t);
     605         [ -  + ]:        671 :   if (r.isRational())
     606                 :            :   {
     607                 :            :     return RewriteResponse(REWRITE_DONE,
     608                 :          0 :                            rewriter::mkConst(d_nm, r.toRational()));
     609                 :            :   }
     610                 :        671 :   return RewriteResponse(REWRITE_DONE, t);
     611                 :            : }
     612                 :            : 
     613                 :          0 : RewriteResponse ArithRewriter::rewriteVariable(TNode t)
     614                 :            : {
     615                 :          0 :   Assert(t.isVar());
     616                 :            : 
     617                 :          0 :   return RewriteResponse(REWRITE_DONE, t);
     618                 :            : }
     619                 :            : 
     620                 :      23556 : RewriteResponse ArithRewriter::rewriteNeg(TNode t, bool pre)
     621                 :            : {
     622 [ -  + ][ -  + ]:      23556 :   Assert(t.getKind() == Kind::NEG);
                 [ -  - ]
     623                 :            : 
     624                 :      23556 :   NodeManager* nm = nodeManager();
     625         [ +  + ]:      23556 :   if (t[0].isConst())
     626                 :            :   {
     627                 :      10949 :     Rational neg = -(t[0].getConst<Rational>());
     628                 :            :     return RewriteResponse(REWRITE_DONE,
     629                 :      21898 :                            nm->mkConstRealOrInt(t.getType(), neg));
     630                 :      10949 :   }
     631         [ +  + ]:      12607 :   if (rewriter::isRAN(t[0]))
     632                 :            :   {
     633                 :            :     return RewriteResponse(REWRITE_DONE,
     634                 :          4 :                            rewriter::mkConst(d_nm, -rewriter::getRAN(t[0])));
     635                 :            :   }
     636                 :            : 
     637                 :            :   Node noUminus =
     638                 :      25210 :       nm->mkNode(Kind::MULT, rewriter::mkConst(d_nm, Rational(-1)), t[0]);
     639         [ +  - ]:      12605 :   if (pre)
     640                 :            :   {
     641                 :      12605 :     return RewriteResponse(REWRITE_DONE, noUminus);
     642                 :            :   }
     643                 :            :   else
     644                 :            :   {
     645                 :          0 :     return RewriteResponse(REWRITE_AGAIN, noUminus);
     646                 :            :   }
     647                 :      12605 : }
     648                 :            : 
     649                 :     557726 : RewriteResponse ArithRewriter::rewriteSub(TNode t)
     650                 :            : {
     651 [ -  + ][ -  + ]:     557726 :   Assert(t.getKind() == Kind::SUB);
                 [ -  - ]
     652 [ -  + ][ -  + ]:     557726 :   Assert(t.getNumChildren() == 2);
                 [ -  - ]
     653                 :            : 
     654                 :     557726 :   NodeManager* nm = nodeManager();
     655         [ +  + ]:     557726 :   if (t[0] == t[1])
     656                 :            :   {
     657                 :            :     return RewriteResponse(REWRITE_DONE,
     658                 :       3140 :                            nm->mkConstRealOrInt(t.getType(), Rational(0)));
     659                 :            :   }
     660                 :            :   return RewriteResponse(
     661                 :            :       REWRITE_AGAIN_FULL,
     662                 :    1112312 :       nm->mkNode(Kind::ADD,
     663                 :            :                  t[0],
     664                 :    2224624 :                  nm->mkNode(Kind::MULT,
     665                 :    1112312 :                             nm->mkConstRealOrInt(t[1].getType(), Rational(-1)),
     666                 :     556156 :                             t[1])));
     667                 :            : }
     668                 :            : 
     669                 :    3155228 : RewriteResponse ArithRewriter::preRewritePlus(TNode t)
     670                 :            : {
     671 [ -  + ][ -  + ]:    3155228 :   Assert(t.getKind() == Kind::ADD);
                 [ -  - ]
     672                 :    3155228 :   std::vector<std::pair<TNode, Rational>> children;
     673         [ +  + ]:    3155228 :   if (!flattenAndCollectSum(t, children, Kind::ADD))
     674                 :            :   {
     675                 :    2787591 :     return RewriteResponse(REWRITE_DONE, t);
     676                 :            :   }
     677                 :     367637 :   NodeManager* nm = nodeManager();
     678                 :     367637 :   NodeBuilder nb(nm, Kind::ADD);
     679                 :     367637 :   Rational coeff(0);
     680         [ +  + ]:    1757538 :   for (const std::pair<TNode, Rational>& c : children)
     681                 :            :   {
     682         [ +  + ]:    1389901 :     if (c.first.isConst())
     683                 :            :     {
     684                 :     578185 :       coeff += c.first.getConst<Rational>() * c.second;
     685                 :            :     }
     686         [ +  + ]:     811716 :     else if (c.second.isOne())
     687                 :            :     {
     688                 :     209692 :       nb << c.first;
     689                 :            :     }
     690                 :            :     else
     691                 :            :     {
     692                 :     602024 :       nb << nm->mkNode(Kind::MULT, nm->mkConstRealOrInt(c.second), c.first);
     693                 :            :     }
     694                 :            :   }
     695 [ +  + ][ +  + ]:     367637 :   if (!coeff.isZero() || nb.getNumChildren() == 0)
                 [ +  + ]
     696                 :            :   {
     697                 :     289631 :     nb << nm->mkConstRealOrInt(t.getType(), coeff);
     698                 :            :   }
     699         [ +  + ]:     367637 :   Node ret = nb.getNumChildren() == 1 ? nb.getChild(0) : nb;
     700                 :     367637 :   ret = rewriter::maybeEnsureReal(t.getType(), ret);
     701                 :     367637 :   return RewriteResponse(REWRITE_DONE, ret);
     702                 :    3155228 : }
     703                 :            : 
     704                 :    2246907 : RewriteResponse ArithRewriter::postRewritePlus(TNode t)
     705                 :            : {
     706 [ -  + ][ -  + ]:    2246907 :   Assert(t.getKind() == Kind::ADD);
                 [ -  - ]
     707 [ -  + ][ -  + ]:    2246907 :   Assert(t.getNumChildren() > 1);
                 [ -  - ]
     708                 :            : 
     709                 :    2246907 :   rewriter::Sum sum;
     710                 :    2246907 :   std::vector<std::pair<TNode, Rational>> children;
     711         [ +  + ]:    2246907 :   if (!flattenAndCollectSum(t, children, Kind::ADD, Kind::TO_REAL))
     712                 :            :   {
     713                 :    2103928 :     rewriter::addToSum(sum, t);
     714                 :            :   }
     715                 :            :   else
     716                 :            :   {
     717                 :     142979 :     Rational coeff(0);
     718         [ +  + ]:     679869 :     for (const std::pair<TNode, Rational>& c : children)
     719                 :            :     {
     720         [ +  + ]:     536890 :       if (c.first.isConst())
     721                 :            :       {
     722                 :     190758 :         coeff += c.first.getConst<Rational>() * c.second;
     723                 :            :       }
     724         [ +  + ]:     346132 :       else if (c.second.isOne())
     725                 :            :       {
     726                 :     131757 :         rewriter::addToSum(sum, c.first);
     727                 :            :       }
     728                 :            :       else
     729                 :            :       {
     730                 :     214375 :         RealAlgebraicNumber mul = RealAlgebraicNumber(c.second);
     731                 :     214375 :         rewriter::addMonomialToSum(sum, c.first, mul);
     732                 :     214375 :       }
     733                 :            :     }
     734         [ +  + ]:     142979 :     if (!coeff.isZero())
     735                 :            :     {
     736                 :      89563 :       rewriter::addToSum(sum, nodeManager()->mkConstRealOrInt(coeff));
     737                 :            :     }
     738                 :     142979 :   }
     739                 :    2246907 :   Node retSum = rewriter::collectSum(d_nm, sum);
     740                 :    2246907 :   retSum = rewriter::maybeEnsureReal(t.getType(), retSum);
     741                 :    4493814 :   return RewriteResponse(REWRITE_DONE, retSum);
     742                 :    2246907 : }
     743                 :            : 
     744                 :    1312179 : RewriteResponse ArithRewriter::preRewriteMult(TNode node)
     745                 :            : {
     746 [ +  + ][ +  - ]:    1312179 :   Assert(node.getKind() == Kind::MULT
         [ -  + ][ -  + ]
                 [ -  - ]
     747                 :            :          || node.getKind() == Kind::NONLINEAR_MULT);
     748                 :            : 
     749         [ +  + ]:    1312179 :   if (auto res = rewriter::getZeroChild(node); res)
     750                 :            :   {
     751                 :            :     return RewriteResponse(REWRITE_DONE,
     752                 :     229818 :                            rewriter::maybeEnsureReal(node.getType(), *res));
     753         [ +  + ]:    1312179 :   }
     754                 :    1197270 :   return RewriteResponse(REWRITE_DONE, node);
     755                 :            : }
     756                 :            : 
     757                 :    1080012 : RewriteResponse ArithRewriter::postRewriteMult(TNode t)
     758                 :            : {
     759 [ +  + ][ +  - ]:    1080012 :   Assert(t.getKind() == Kind::MULT || t.getKind() == Kind::NONLINEAR_MULT);
         [ -  + ][ -  + ]
                 [ -  - ]
     760 [ -  + ][ -  + ]:    1080012 :   Assert(t.getNumChildren() >= 2);
                 [ -  - ]
     761                 :            : 
     762                 :    1080012 :   std::vector<TNode> children;
     763                 :    1080012 :   expr::algorithm::flatten(
     764                 :            :       t, children, Kind::MULT, Kind::NONLINEAR_MULT, Kind::TO_REAL);
     765                 :            : 
     766         [ +  + ]:    1080012 :   if (auto res = rewriter::getZeroChild(children); res)
     767                 :            :   {
     768                 :            :     return RewriteResponse(REWRITE_DONE,
     769                 :      11190 :                            rewriter::maybeEnsureReal(t.getType(), *res));
     770         [ +  + ]:    1080012 :   }
     771                 :            : 
     772                 :    1074417 :   RewriteStatus rs = REWRITE_DONE;
     773                 :    1074417 :   Node ret;
     774                 :            :   // Distribute over addition
     775         [ +  + ]:    1074417 :   if (std::any_of(children.begin(), children.end(), [](TNode child) {
     776                 :    2389863 :         return child.getKind() == Kind::ADD;
     777                 :            :       }))
     778                 :            :   {
     779                 :            :     // if we distribute multiplication, we rewrite again to ensure the
     780                 :            :     // sum is sorted.
     781                 :      68448 :     rs = REWRITE_AGAIN_FULL;
     782                 :      68448 :     ret = rewriter::distributeMultiplication(d_nm, children);
     783                 :            :   }
     784                 :            :   else
     785                 :            :   {
     786                 :    1005969 :     RealAlgebraicNumber ran = RealAlgebraicNumber(Integer(1));
     787                 :    1005969 :     std::vector<Node> leafs;
     788                 :            : 
     789         [ +  + ]:    3262746 :     for (const auto& child : children)
     790                 :            :     {
     791         [ +  + ]:    2256777 :       if (child.isConst())
     792                 :            :       {
     793         [ -  + ]:    1104622 :         if (child.getConst<Rational>().isZero())
     794                 :            :         {
     795                 :            :           return RewriteResponse(REWRITE_DONE,
     796                 :          0 :                                  rewriter::maybeEnsureReal(t.getType(), child));
     797                 :            :         }
     798                 :    1104622 :         ran *= child.getConst<Rational>();
     799                 :            :       }
     800         [ +  + ]:    1152155 :       else if (rewriter::isRAN(child))
     801                 :            :       {
     802                 :        164 :         ran *= rewriter::getRAN(child);
     803                 :            :       }
     804                 :            :       else
     805                 :            :       {
     806                 :    1151991 :         leafs.emplace_back(child);
     807                 :            :       }
     808                 :            :     }
     809                 :    1005969 :     ret = rewriter::mkMultTerm(d_nm, ran, std::move(leafs));
     810 [ +  - ][ +  - ]:    1005969 :   }
     811                 :    1074417 :   ret = rewriter::maybeEnsureReal(t.getType(), ret);
     812                 :    1074417 :   return RewriteResponse(rs, ret);
     813                 :    1080012 : }
     814                 :            : 
     815                 :      16429 : RewriteResponse ArithRewriter::rewriteDiv(TNode t, bool pre)
     816                 :            : {
     817 [ +  + ][ +  - ]:      16429 :   Assert(t.getKind() == Kind::DIVISION_TOTAL || t.getKind() == Kind::DIVISION);
         [ -  + ][ -  + ]
                 [ -  - ]
     818 [ -  + ][ -  + ]:      16429 :   Assert(t.getNumChildren() == 2);
                 [ -  - ]
     819                 :            : 
     820                 :      32858 :   Node left = rewriter::removeToReal(t[0]);
     821                 :      32858 :   Node right = rewriter::removeToReal(t[1]);
     822                 :      16429 :   NodeManager* nm = nodeManager();
     823         [ +  + ]:      16429 :   if (right.isConst())
     824                 :            :   {
     825                 :       6518 :     const Rational& den = right.getConst<Rational>();
     826                 :            : 
     827         [ +  + ]:       6518 :     if (den.isZero())
     828                 :            :     {
     829         [ +  + ]:       1141 :       if (t.getKind() == Kind::DIVISION_TOTAL)
     830                 :            :       {
     831                 :        171 :         Node ret = nm->mkConstReal(0);
     832                 :        171 :         return RewriteResponse(REWRITE_DONE, ret);
     833                 :        171 :       }
     834                 :            :       else
     835                 :            :       {
     836                 :       1940 :         Node ret = nm->mkNode(t.getKind(), left, right);
     837                 :        970 :         return RewriteResponse(REWRITE_DONE, ret);
     838                 :        970 :       }
     839                 :            :     }
     840 [ -  + ][ -  + ]:       5377 :     Assert(den != Rational(0));
                 [ -  - ]
     841                 :            : 
     842         [ +  + ]:       5377 :     if (left.isConst())
     843                 :            :     {
     844                 :       2154 :       const Rational& num = left.getConst<Rational>();
     845                 :       4308 :       return RewriteResponse(REWRITE_DONE, nm->mkConstReal(num / den));
     846                 :            :     }
     847         [ -  + ]:       3223 :     if (rewriter::isRAN(left))
     848                 :            :     {
     849                 :            :       return RewriteResponse(REWRITE_DONE,
     850                 :          0 :                              rewriter::ensureReal(nm->mkRealAlgebraicNumber(
     851                 :          0 :                                  rewriter::getRAN(left) / den)));
     852                 :            :     }
     853                 :            : 
     854                 :       3223 :     Node result = nm->mkConstReal(den.inverse());
     855                 :            :     Node mult =
     856                 :       6446 :         rewriter::ensureReal(nodeManager()->mkNode(Kind::MULT, left, result));
     857         [ +  + ]:       3223 :     if (pre)
     858                 :            :     {
     859                 :       3195 :       return RewriteResponse(REWRITE_DONE, mult);
     860                 :            :     }
     861                 :            :     // requires again full since ensureReal may have added a to_real
     862                 :         28 :     return RewriteResponse(REWRITE_AGAIN_FULL, mult);
     863                 :       3223 :   }
     864         [ +  + ]:       9911 :   if (rewriter::isRAN(right))
     865                 :            :   {
     866                 :          4 :     const RealAlgebraicNumber& den = rewriter::getRAN(right);
     867                 :            :     // mkConst is applied to RAN in this block, which are always Real
     868         [ +  + ]:          4 :     if (left.isConst())
     869                 :            :     {
     870                 :            :       return RewriteResponse(
     871                 :            :           REWRITE_DONE,
     872                 :          4 :           rewriter::ensureReal(rewriter::mkConst(
     873                 :          6 :               d_nm, RealAlgebraicNumber(left.getConst<Rational>()) / den)));
     874                 :            :     }
     875         [ +  - ]:          2 :     if (rewriter::isRAN(left))
     876                 :            :     {
     877                 :            :       return RewriteResponse(REWRITE_DONE,
     878                 :          4 :                              rewriter::ensureReal(rewriter::mkConst(
     879                 :          6 :                                  d_nm, rewriter::getRAN(left) / den)));
     880                 :            :     }
     881                 :            : 
     882                 :          0 :     Node result = rewriter::mkConst(d_nm, den.inverse());
     883                 :            :     Node mult =
     884                 :          0 :         rewriter::ensureReal(nodeManager()->mkNode(Kind::MULT, left, result));
     885         [ -  - ]:          0 :     if (pre)
     886                 :            :     {
     887                 :          0 :       return RewriteResponse(REWRITE_DONE, mult);
     888                 :            :     }
     889                 :            :     // requires again full since ensureReal may have added a to_real
     890                 :          0 :     return RewriteResponse(REWRITE_AGAIN_FULL, mult);
     891                 :          0 :   }
     892                 :            :   // We also convert integral rationals in the numerator to integers,
     893                 :            :   // e.g. (/ 1 x) ---> (/ 1.0 x).
     894         [ +  + ]:       9907 :   if (left.getKind() == Kind::CONST_INTEGER)
     895                 :            :   {
     896                 :         47 :     left = nm->mkConstReal(left.getConst<Rational>());
     897                 :            :   }
     898                 :            :   // may have changed due to removing to_real
     899                 :       9907 :   if (left != t[0] || right != t[1])
     900                 :            :   {
     901                 :        296 :     Node ret = nm->mkNode(t.getKind(), left, right);
     902                 :        148 :     return RewriteResponse(REWRITE_AGAIN_FULL, ret);
     903                 :        148 :   }
     904                 :       9759 :   return RewriteResponse(REWRITE_DONE, t);
     905                 :      16429 : }
     906                 :            : 
     907                 :      23058 : RewriteResponse ArithRewriter::rewriteToReal(TNode t)
     908                 :            : {
     909 [ -  + ][ -  + ]:      23058 :   Assert(t.getKind() == Kind::TO_REAL);
                 [ -  - ]
     910         [ +  + ]:      23058 :   if (!t[0].getType().isInteger())
     911                 :            :   {
     912                 :            :     // if it is already real type, then just return the argument
     913                 :         18 :     return RewriteResponse(REWRITE_DONE, t[0]);
     914                 :            :   }
     915                 :      23040 :   NodeManager* nm = nodeManager();
     916         [ +  + ]:      23040 :   if (t[0].isConst())
     917                 :            :   {
     918                 :            :     // If the argument is constant, return a real constant.
     919                 :       3625 :     const Rational& rat = t[0].getConst<Rational>();
     920                 :       7250 :     return RewriteResponse(REWRITE_DONE, nm->mkConstReal(rat));
     921                 :            :   }
     922         [ -  + ]:      19415 :   if (t[0].getKind() == Kind::TO_REAL)
     923                 :            :   {
     924                 :            :     // (to_real (to_real t)) ---> (to_real t)
     925                 :          0 :     return RewriteResponse(REWRITE_DONE, t[0]);
     926                 :            :   }
     927                 :      19415 :   return RewriteResponse(REWRITE_DONE, t);
     928                 :            : }
     929                 :            : 
     930                 :      12870 : RewriteResponse ArithRewriter::rewriteAbs(TNode t)
     931                 :            : {
     932 [ -  + ][ -  + ]:      12870 :   Assert(t.getKind() == Kind::ABS);
                 [ -  - ]
     933 [ -  + ][ -  + ]:      12870 :   Assert(t.getNumChildren() == 1);
                 [ -  - ]
     934                 :            : 
     935         [ +  + ]:      12870 :   if (t[0].isConst())
     936                 :            :   {
     937                 :        366 :     const Rational& rat = t[0].getConst<Rational>();
     938         [ +  + ]:        366 :     if (rat >= 0)
     939                 :            :     {
     940                 :        361 :       return RewriteResponse(REWRITE_DONE, t[0]);
     941                 :            :     }
     942                 :            :     return RewriteResponse(
     943                 :          5 :         REWRITE_DONE, nodeManager()->mkConstRealOrInt(t[0].getType(), -rat));
     944                 :            :   }
     945         [ +  + ]:      12504 :   if (rewriter::isRAN(t[0]))
     946                 :            :   {
     947                 :          2 :     const RealAlgebraicNumber& ran = rewriter::getRAN(t[0]);
     948         [ +  + ]:          2 :     if (ran >= RealAlgebraicNumber())
     949                 :            :     {
     950                 :          1 :       return RewriteResponse(REWRITE_DONE, t[0]);
     951                 :            :     }
     952                 :            :     return RewriteResponse(REWRITE_DONE,
     953                 :          2 :                            nodeManager()->mkRealAlgebraicNumber(-ran));
     954                 :            :   }
     955                 :      12502 :   return RewriteResponse(REWRITE_DONE, t);
     956                 :            : }
     957                 :            : 
     958                 :      15052 : RewriteResponse ArithRewriter::rewriteIntsDivMod(TNode t)
     959                 :            : {
     960                 :      15052 :   NodeManager* nm = nodeManager();
     961                 :      15052 :   Kind k = t.getKind();
     962         [ +  + ]:      15052 :   if (k == Kind::INTS_MODULUS)
     963                 :            :   {
     964                 :      11223 :     if (t[1].isConst() && !t[1].getConst<Rational>().isZero())
     965                 :            :     {
     966                 :            :       // can immediately replace by INTS_MODULUS_TOTAL
     967                 :       4850 :       Node ret = nm->mkNode(Kind::INTS_MODULUS_TOTAL, t[0], t[1]);
     968                 :       2425 :       return returnRewrite(t, ret, Rewrite::MOD_TOTAL_BY_CONST);
     969                 :       2425 :     }
     970                 :            :   }
     971         [ +  + ]:      12627 :   if (k == Kind::INTS_DIVISION)
     972                 :            :   {
     973                 :       3829 :     if (t[1].isConst() && !t[1].getConst<Rational>().isZero())
     974                 :            :     {
     975                 :            :       // can immediately replace by INTS_DIVISION_TOTAL
     976                 :        880 :       Node ret = nm->mkNode(Kind::INTS_DIVISION_TOTAL, t[0], t[1]);
     977                 :        440 :       return returnRewrite(t, ret, Rewrite::DIV_TOTAL_BY_CONST);
     978                 :        440 :     }
     979                 :            :   }
     980                 :      12187 :   return RewriteResponse(REWRITE_DONE, t);
     981                 :            : }
     982                 :            : 
     983                 :      46385 : RewriteResponse ArithRewriter::rewriteIntsDivModTotal(TNode t, bool pre)
     984                 :            : {
     985         [ +  + ]:      46385 :   if (pre)
     986                 :            :   {
     987                 :            :     // do not rewrite at prewrite.
     988                 :      25908 :     return RewriteResponse(REWRITE_DONE, t);
     989                 :            :   }
     990                 :      20477 :   NodeManager* nm = nodeManager();
     991                 :      20477 :   Kind k = t.getKind();
     992 [ +  + ][ +  - ]:      20477 :   Assert(k == Kind::INTS_MODULUS_TOTAL || k == Kind::INTS_DIVISION_TOTAL);
         [ -  + ][ -  + ]
                 [ -  - ]
     993                 :      20477 :   TNode n = t[0];
     994                 :      20477 :   TNode d = t[1];
     995                 :      20477 :   bool dIsConstant = d.isConst();
     996 [ +  + ][ +  + ]:      20477 :   if (dIsConstant && d.getConst<Rational>().isZero())
                 [ +  + ]
     997                 :            :   {
     998                 :            :     // (div_total x 0) ---> 0 or (mod_total x 0) ---> x
     999                 :        340 :     Node ret = k == Kind::INTS_MODULUS_TOTAL ? Node(t[0]) : nm->mkConstInt(0);
    1000                 :        210 :     return returnRewrite(t, ret, Rewrite::DIV_MOD_BY_ZERO);
    1001                 :        210 :   }
    1002 [ +  + ][ +  + ]:      20267 :   else if (dIsConstant && d.getConst<Rational>().isOne())
                 [ +  + ]
    1003                 :            :   {
    1004         [ +  + ]:        562 :     if (k == Kind::INTS_MODULUS_TOTAL)
    1005                 :            :     {
    1006                 :            :       // (mod_total x 1) --> 0
    1007                 :         98 :       return returnRewrite(t, nm->mkConstInt(0), Rewrite::MOD_BY_ONE);
    1008                 :            :     }
    1009 [ -  + ][ -  + ]:        464 :     Assert(k == Kind::INTS_DIVISION_TOTAL);
                 [ -  - ]
    1010                 :            :     // (div_total x 1) --> x
    1011                 :        464 :     return returnRewrite(t, n, Rewrite::DIV_BY_ONE);
    1012                 :            :   }
    1013 [ +  + ][ +  + ]:      19705 :   else if (dIsConstant && d.getConst<Rational>().sgn() < 0)
                 [ +  + ]
    1014                 :            :   {
    1015                 :            :     // pull negation
    1016                 :            :     // (div_total x (- c)) ---> (- (div_total x c))
    1017                 :            :     // (mod_total x (- c)) ---> (mod_total x c)
    1018                 :        360 :     Node nn = nm->mkNode(k, t[0], nm->mkConstInt(-t[1].getConst<Rational>()));
    1019 [ +  + ][ +  + ]:        180 :     Node ret = k == Kind::INTS_DIVISION_TOTAL ? nm->mkNode(Kind::NEG, nn) : nn;
                 [ -  - ]
    1020                 :        180 :     return returnRewrite(t, ret, Rewrite::DIV_MOD_PULL_NEG_DEN);
    1021                 :        180 :   }
    1022 [ +  + ][ +  + ]:      19525 :   else if (dIsConstant && n.isConst())
                 [ +  + ]
    1023                 :            :   {
    1024 [ -  + ][ -  + ]:       3426 :     Assert(d.getConst<Rational>().isIntegral());
                 [ -  - ]
    1025 [ -  + ][ -  + ]:       3426 :     Assert(n.getConst<Rational>().isIntegral());
                 [ -  - ]
    1026 [ -  + ][ -  + ]:       3426 :     Assert(!d.getConst<Rational>().isZero());
                 [ -  - ]
    1027                 :       3426 :     Integer di = d.getConst<Rational>().getNumerator();
    1028                 :       3426 :     Integer ni = n.getConst<Rational>().getNumerator();
    1029                 :            : 
    1030                 :       3426 :     bool isDiv = (k == Kind::INTS_DIVISION_TOTAL);
    1031                 :            : 
    1032                 :            :     Integer result = isDiv ? ni.euclidianDivideQuotient(di)
    1033         [ +  + ]:       3426 :                            : ni.euclidianDivideRemainder(di);
    1034                 :            : 
    1035                 :            :     // constant evaluation
    1036                 :            :     // (mod_total c1 c2) ---> c3 or (div_total c1 c2) ---> c3
    1037                 :       3426 :     Node resultNode = nm->mkConstInt(Rational(result));
    1038                 :       3426 :     return returnRewrite(t, resultNode, Rewrite::CONST_EVAL);
    1039                 :       3426 :   }
    1040         [ +  + ]:      16099 :   if (k == Kind::INTS_MODULUS_TOTAL)
    1041                 :            :   {
    1042                 :            :     // Note these rewrites do not need to account for modulus by zero as being
    1043                 :            :     // a UF, which is handled by the reduction of INTS_MODULUS.
    1044                 :       9589 :     Kind k0 = t[0].getKind();
    1045                 :       9589 :     if (k0 == Kind::INTS_MODULUS_TOTAL && t[0][1] == t[1])
    1046                 :            :     {
    1047                 :            :       // (mod_total (mod_total x c) c) --> (mod x c)
    1048                 :         41 :       return returnRewrite(t, t[0], Rewrite::MOD_OVER_MOD);
    1049                 :            :     }
    1050 [ +  + ][ +  + ]:       9548 :     else if (k0 == Kind::NONLINEAR_MULT || k0 == Kind::MULT || k0 == Kind::ADD)
                 [ +  + ]
    1051                 :            :     {
    1052                 :            :       // can drop all
    1053                 :       3500 :       std::vector<Node> newChildren;
    1054                 :       3500 :       bool childChanged = false;
    1055         [ +  + ]:      11694 :       for (const Node& tc : t[0])
    1056                 :            :       {
    1057                 :       8194 :         if (tc.getKind() == Kind::INTS_MODULUS_TOTAL && tc[1] == t[1])
    1058                 :            :         {
    1059                 :         52 :           newChildren.push_back(tc[0]);
    1060                 :         52 :           childChanged = true;
    1061                 :         52 :           continue;
    1062                 :            :         }
    1063                 :       8142 :         newChildren.push_back(tc);
    1064         [ +  + ]:      11694 :       }
    1065         [ +  + ]:       3500 :       if (childChanged)
    1066                 :            :       {
    1067                 :            :         // (mod_total (op ... (mod_total x c) ...) c) --->
    1068                 :            :         // (mod_total (op ... x ...) c) where
    1069                 :            :         // op is one of { NONLINEAR_MULT, MULT, ADD }.
    1070                 :         52 :         Node ret = nm->mkNode(k0, newChildren);
    1071                 :         52 :         ret = nm->mkNode(Kind::INTS_MODULUS_TOTAL, ret, t[1]);
    1072                 :         52 :         return returnRewrite(t, ret, Rewrite::MOD_CHILD_MOD);
    1073                 :         52 :       }
    1074         [ +  + ]:       3500 :     }
    1075                 :            :   }
    1076                 :            :   else
    1077                 :            :   {
    1078 [ -  + ][ -  + ]:       6510 :     Assert(k == Kind::INTS_DIVISION_TOTAL);
                 [ -  - ]
    1079                 :            :     // Note these rewrites do not need to account for division by zero as being
    1080                 :            :     // a UF, which is handled by the reduction of INTS_DIVISION.
    1081                 :       6510 :     if (t[0].getKind() == Kind::INTS_MODULUS_TOTAL && t[0][1] == t[1])
    1082                 :            :     {
    1083                 :            :       // (div_total (mod_total x c) c) --> 0
    1084                 :          0 :       Node ret = nm->mkConstInt(0);
    1085                 :          0 :       return returnRewrite(t, ret, Rewrite::DIV_OVER_MOD);
    1086                 :          0 :     }
    1087                 :            :   }
    1088                 :      16006 :   return RewriteResponse(REWRITE_DONE, t);
    1089                 :      20477 : }
    1090                 :            : 
    1091                 :       4315 : RewriteResponse ArithRewriter::rewriteExtIntegerOp(TNode t)
    1092                 :            : {
    1093 [ +  + ][ +  - ]:       4315 :   Assert(t.getKind() == Kind::TO_INTEGER || t.getKind() == Kind::IS_INTEGER);
         [ -  + ][ -  + ]
                 [ -  - ]
    1094                 :       4315 :   bool isPred = t.getKind() == Kind::IS_INTEGER;
    1095                 :       4315 :   NodeManager* nm = nodeManager();
    1096         [ +  + ]:       4315 :   if (t[0].isConst())
    1097                 :            :   {
    1098                 :        500 :     Node ret;
    1099         [ +  + ]:        500 :     if (isPred)
    1100                 :            :     {
    1101                 :         20 :       ret = nm->mkConst(t[0].getConst<Rational>().isIntegral());
    1102                 :            :     }
    1103                 :            :     else
    1104                 :            :     {
    1105                 :        480 :       ret = nm->mkConstInt(Rational(t[0].getConst<Rational>().floor()));
    1106                 :            :     }
    1107                 :        500 :     return returnRewrite(t, ret, Rewrite::INT_EXT_CONST);
    1108                 :        500 :   }
    1109         [ +  + ]:       3815 :   if (t[0].getType().isInteger())
    1110                 :            :   {
    1111 [ -  + ][ +  - ]:        230 :     Node ret = isPred ? nm->mkConst(true) : Node(t[0]);
                 [ -  - ]
    1112                 :        115 :     return returnRewrite(t, ret, Rewrite::INT_EXT_INT);
    1113                 :        115 :   }
    1114         [ +  + ]:       3700 :   if (t[0].getKind() == Kind::TO_REAL)
    1115                 :            :   {
    1116                 :        238 :     Node ret = nm->mkNode(t.getKind(), t[0][0]);
    1117                 :        119 :     return returnRewrite(t, ret, Rewrite::INT_EXT_TO_REAL);
    1118                 :        119 :   }
    1119         [ +  - ]:       3581 :   if (d_expertEnabled)
    1120                 :            :   {
    1121         [ +  + ]:       3581 :     if (t[0].getKind() == Kind::PI)
    1122                 :            :     {
    1123 [ +  + ][ +  + ]:         14 :       Node ret = isPred ? nm->mkConst(false) : nm->mkConstInt(Rational(3));
                 [ -  - ]
    1124                 :         12 :       return returnRewrite(t, ret, Rewrite::INT_EXT_PI);
    1125                 :         12 :     }
    1126                 :            :   }
    1127                 :       3569 :   return RewriteResponse(REWRITE_DONE, t);
    1128                 :            : }
    1129                 :            : 
    1130                 :       2004 : RewriteResponse ArithRewriter::postRewriteIAnd(TNode t)
    1131                 :            : {
    1132 [ -  + ][ -  + ]:       2004 :   Assert(t.getKind() == Kind::IAND);
                 [ -  - ]
    1133                 :       2004 :   uint32_t bsize = t.getOperator().getConst<IntAnd>().d_size;
    1134                 :       2004 :   NodeManager* nm = nodeManager();
    1135                 :            :   // if constant, we eliminate
    1136                 :       2004 :   if (t[0].isConst() && t[1].isConst())
    1137                 :            :   {
    1138                 :        940 :     Node iToBvop = nm->mkConst(IntToBitVector(bsize));
    1139                 :       1880 :     Node arg1 = nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, t[0]);
    1140                 :       1880 :     Node arg2 = nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, t[1]);
    1141                 :       1880 :     Node bvand = nm->mkNode(Kind::BITVECTOR_AND, arg1, arg2);
    1142                 :        940 :     Node ret = nm->mkNode(Kind::BITVECTOR_UBV_TO_INT, bvand);
    1143                 :        940 :     return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1144                 :        940 :   }
    1145         [ +  + ]:       1064 :   else if (t[0] > t[1])
    1146                 :            :   {
    1147                 :            :     // ((_ iand k) x y) ---> ((_ iand k) y x) if x > y by node ordering
    1148                 :        174 :     Node ret = nm->mkNode(Kind::IAND, t.getOperator(), t[1], t[0]);
    1149                 :         87 :     return RewriteResponse(REWRITE_AGAIN, ret);
    1150                 :         87 :   }
    1151         [ +  + ]:        977 :   else if (t[0] == t[1])
    1152                 :            :   {
    1153                 :            :     // ((_ iand k) x x) ---> (mod x 2^k)
    1154                 :         24 :     Node twok = nm->mkConstInt(Rational(Integer(2).pow(bsize)));
    1155                 :         24 :     Node ret = nm->mkNode(Kind::INTS_MODULUS, t[0], twok);
    1156                 :         12 :     return RewriteResponse(REWRITE_AGAIN, ret);
    1157                 :         12 :   }
    1158                 :            :   // simplifications involving constants
    1159         [ +  + ]:       2868 :   for (unsigned i = 0; i < 2; i++)
    1160                 :            :   {
    1161         [ +  + ]:       1929 :     if (!t[i].isConst())
    1162                 :            :     {
    1163                 :       1684 :       continue;
    1164                 :            :     }
    1165         [ +  + ]:        245 :     if (t[i].getConst<Rational>().sgn() == 0)
    1166                 :            :     {
    1167                 :            :       // ((_ iand k) 0 y) ---> 0
    1168                 :          1 :       return RewriteResponse(REWRITE_DONE, t[i]);
    1169                 :            :     }
    1170         [ +  + ]:        244 :     if (t[i].getConst<Rational>().getNumerator() == Integer(2).pow(bsize) - 1)
    1171                 :            :     {
    1172                 :            :       // ((_ iand k) 111...1 y) ---> (mod y 2^k)
    1173                 :         50 :       Node twok = nm->mkConstInt(Rational(Integer(2).pow(bsize)));
    1174                 :         50 :       Node ret = nm->mkNode(Kind::INTS_MODULUS, t[1 - i], twok);
    1175                 :         25 :       return RewriteResponse(REWRITE_AGAIN, ret);
    1176                 :         25 :     }
    1177                 :            :   }
    1178                 :        939 :   return RewriteResponse(REWRITE_DONE, t);
    1179                 :            : }
    1180                 :            : 
    1181                 :        775 : RewriteResponse ArithRewriter::postRewritePIAnd(TNode t)
    1182                 :            : {
    1183 [ -  + ][ -  + ]:        775 :   Assert(t.getKind() == Kind::PIAND);
                 [ -  - ]
    1184                 :        775 :   NodeManager* nm = nodeManager();
    1185                 :            :   // simplifications involving constants
    1186 [ +  + ][ -  - ]:        775 :   if (t[0].isConst()
    1187 [ +  + ][ +  + ]:       1570 :       && (t[0].getConst<Rational>().sgn() == 0
         [ +  - ][ -  - ]
    1188 [ +  + ][ +  + ]:        795 :           || t[0].getConst<Rational>().sgn() == -1))
         [ +  + ][ -  - ]
    1189                 :            :   {
    1190                 :         80 :     return RewriteResponse(REWRITE_DONE, nm->mkConstInt(Rational(0)));
    1191                 :            :   }
    1192         [ +  + ]:       2161 :   for (unsigned i = 1; i < 3; i++)
    1193                 :            :   {
    1194         [ +  + ]:       1454 :     if (!t[i].isConst())
    1195                 :            :     {
    1196                 :       1426 :       continue;
    1197                 :            :     }
    1198         [ +  + ]:        108 :     if (t[i].getConst<Rational>().sgn() == 0)
    1199                 :            :     {
    1200                 :            :       // (piand k 0 y) ---> 0
    1201                 :         44 :       return RewriteResponse(REWRITE_DONE, nm->mkConstInt(Rational(0)));
    1202                 :            :     }
    1203         [ +  + ]:         86 :     if (!t[0].isConst())
    1204                 :            :     {
    1205                 :         80 :       continue;
    1206                 :            :     }
    1207                 :          6 :     size_t bsize = t[0].getConst<Rational>().getNumerator().toUnsignedInt();
    1208                 :          6 :     Node twok = nm->mkNode(Kind::POW2, t[0]);
    1209                 :         12 :     Node maxsign = nm->mkConstInt(Rational(Integer(2).pow(bsize) - 1));
    1210                 :         12 :     if (t[i].getConst<Rational>().getNumerator()
    1211         [ +  - ]:         18 :         == maxsign.getConst<Rational>().getNumerator())
    1212                 :            :     {
    1213                 :            :       // (piand k 111...1 y) ---> (mod y 2^k)
    1214         [ +  - ]:          6 :       if (i == 1)
    1215                 :            :       {
    1216                 :         12 :         Node ret = nm->mkNode(Kind::INTS_MODULUS, t[2], twok);
    1217                 :          6 :         return RewriteResponse(REWRITE_AGAIN, ret);
    1218                 :          6 :       }
    1219         [ -  - ]:          0 :       else if (i == 2)
    1220                 :            :       {
    1221                 :          0 :         Node ret = nm->mkNode(Kind::INTS_MODULUS, t[1], twok);
    1222                 :          0 :         return RewriteResponse(REWRITE_AGAIN, ret);
    1223                 :          0 :       }
    1224                 :            :     }
    1225 [ -  + ][ -  + ]:         12 :   }
    1226                 :            :   // if constant, we eliminate
    1227                 :        707 :   if (t[0].isConst() && t[1].isConst() && t[2].isConst())
    1228                 :            :   {
    1229                 :          0 :     size_t bsize = t[0].getConst<Rational>().getNumerator().toUnsignedInt();
    1230                 :          0 :     Node iToBvop = nm->mkConst(IntToBitVector(bsize));
    1231                 :          0 :     Node arg1 = nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, t[1]);
    1232                 :          0 :     Node arg2 = nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, t[2]);
    1233                 :          0 :     Node bvand = nm->mkNode(Kind::BITVECTOR_AND, arg1, arg2);
    1234                 :          0 :     Node ret = nm->mkNode(Kind::BITVECTOR_UBV_TO_INT, bvand);
    1235                 :          0 :     return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1236                 :          0 :   }
    1237         [ +  + ]:        707 :   else if (t[1] > t[2])
    1238                 :            :   {
    1239                 :            :     // (piand k x y) ---> (piand k y x) if x > y by node ordering
    1240                 :        184 :     Node ret = nm->mkNode(Kind::PIAND, t[0], t[2], t[1]);
    1241                 :         92 :     return RewriteResponse(REWRITE_AGAIN, ret);
    1242                 :         92 :   }
    1243         [ +  + ]:        615 :   else if (t[1] == t[2])
    1244                 :            :   {
    1245                 :            :     // (piand k x x) ---> (mod x 2^k)
    1246                 :         20 :     Node twok = nm->mkNode(Kind::POW2, t[0]);
    1247                 :         40 :     Node ret = nm->mkNode(Kind::INTS_MODULUS, t[1], twok);
    1248                 :         20 :     return RewriteResponse(REWRITE_AGAIN, ret);
    1249                 :         20 :   }
    1250                 :        595 :   return RewriteResponse(REWRITE_DONE, t);
    1251                 :            : }
    1252                 :            : 
    1253                 :       1949 : RewriteResponse ArithRewriter::postRewritePow2(TNode t)
    1254                 :            : {
    1255 [ -  + ][ -  + ]:       1949 :   Assert(t.getKind() == Kind::POW2);
                 [ -  - ]
    1256                 :            :   // if constant, we eliminate
    1257         [ +  + ]:       1949 :   if (t[0].isConst())
    1258                 :            :   {
    1259                 :            :     // pow2 is only supported for integers
    1260         [ +  - ]:       1908 :     Trace("arith-rewriter")
    1261                 :        954 :         << "ArithRewriter::postRewritePow2, t:" << t << std::endl;
    1262 [ -  + ][ -  + ]:        954 :     Assert(t[0].getType().isInteger());
                 [ -  - ]
    1263                 :            :     // use the evaluator definition for rewriting this
    1264                 :        954 :     Evaluator eval(nullptr);
    1265                 :       1908 :     Node ret = eval.eval(t, {}, {});
    1266         [ +  + ]:        954 :     if (!ret.isNull())
    1267                 :            :     {
    1268                 :        938 :       return RewriteResponse(REWRITE_DONE, ret);
    1269                 :            :     }
    1270         [ +  + ]:        954 :   }
    1271                 :       1011 :   return RewriteResponse(REWRITE_DONE, t);
    1272                 :            : }
    1273                 :            : 
    1274                 :        142 : RewriteResponse ArithRewriter::postRewriteIntsIsPow2(TNode t)
    1275                 :            : {
    1276 [ -  + ][ -  + ]:        142 :   Assert(t.getKind() == Kind::INTS_ISPOW2);
                 [ -  - ]
    1277                 :            :   // if constant, we eliminate
    1278         [ +  - ]:        142 :   if (t[0].isConst())
    1279                 :            :   {
    1280                 :            :     // pow2 is only supported for integers
    1281 [ -  + ][ -  + ]:        142 :     Assert(t[0].getType().isInteger());
                 [ -  - ]
    1282                 :        142 :     Integer i = t[0].getConst<Rational>().getNumerator();
    1283                 :            : 
    1284                 :        284 :     return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, i.isPow2()));
    1285                 :        142 :   }
    1286                 :          0 :   return RewriteResponse(REWRITE_DONE, t);
    1287                 :            : }
    1288                 :        215 : RewriteResponse ArithRewriter::postRewriteIntsLog2(TNode t)
    1289                 :            : {
    1290 [ -  + ][ -  + ]:        215 :   Assert(t.getKind() == Kind::INTS_LOG2);
                 [ -  - ]
    1291                 :            :   // if constant, we eliminate
    1292         [ +  + ]:        215 :   if (t[0].isConst())
    1293                 :            :   {
    1294                 :            :     // log2 is only supported for integers
    1295 [ -  + ][ -  + ]:        159 :     Assert(t[0].getType().isInteger());
                 [ -  - ]
    1296                 :        159 :     const Rational& r = t[0].getConst<Rational>();
    1297                 :            :     // default to 0 for negative inputs
    1298         [ +  + ]:        159 :     if (r.sgn() < 0)
    1299                 :            :     {
    1300                 :          2 :       return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, Integer(0)));
    1301                 :            :     }
    1302                 :            :     // for non-negative inputs, this
    1303                 :            :     // is captured by `length()` of `Integer`.
    1304                 :        158 :     Integer i = r.getNumerator();
    1305                 :        158 :     size_t const length = i.length();
    1306                 :            :     return RewriteResponse(REWRITE_DONE,
    1307                 :        316 :                            rewriter::mkConst(d_nm, Integer(length - 1)));
    1308                 :        158 :   }
    1309                 :         56 :   return RewriteResponse(REWRITE_DONE, t);
    1310                 :            : }
    1311                 :            : 
    1312                 :       7881 : RewriteResponse ArithRewriter::postRewriteTranscendental(TNode t)
    1313                 :            : {
    1314         [ +  - ]:      15762 :   Trace("arith-tf-rewrite")
    1315                 :       7881 :       << "Rewrite transcendental function : " << t << std::endl;
    1316 [ -  + ][ -  + ]:       7881 :   Assert(t.getTypeOrNull(true).isReal());
                 [ -  - ]
    1317                 :       7881 :   NodeManager* nm = nodeManager();
    1318 [ +  + ][ +  + ]:       7881 :   switch (t.getKind())
         [ +  + ][ +  + ]
    1319                 :            :   {
    1320                 :       1365 :     case Kind::EXPONENTIAL:
    1321                 :            :     {
    1322         [ +  + ]:       1365 :       if (t[0].isConst())
    1323                 :            :       {
    1324                 :        779 :         Rational r = t[0].getConst<Rational>();
    1325         [ +  + ]:        779 :         if (r.sgn() == 0)
    1326                 :            :         {
    1327                 :         50 :           Node one = nm->mkConstReal(Rational(1));
    1328                 :            :           // (= (exp 0.0) 1.0)
    1329                 :         50 :           return RewriteResponse(REWRITE_DONE, one);
    1330                 :         50 :         }
    1331                 :            :         else
    1332                 :            :         {
    1333                 :        729 :           return RewriteResponse(REWRITE_DONE, t);
    1334                 :            :         }
    1335                 :        779 :       }
    1336         [ +  + ]:        586 :       else if (t[0].getKind() == Kind::ADD)
    1337                 :            :       {
    1338                 :         61 :         std::vector<Node> product;
    1339         [ +  + ]:        183 :         for (const Node tc : t[0])
    1340                 :            :         {
    1341                 :        122 :           Node tcr = rewriter::ensureReal(tc);
    1342                 :        122 :           product.push_back(nm->mkNode(Kind::EXPONENTIAL, tcr));
    1343                 :        183 :         }
    1344                 :            :         // We need to do a full rewrite here, since we can get exponentials of
    1345                 :            :         // constants, e.g. when we are rewriting exp(2 + x)
    1346                 :            :         return RewriteResponse(REWRITE_AGAIN_FULL,
    1347                 :        122 :                                nm->mkNode(Kind::MULT, product));
    1348                 :         61 :       }
    1349                 :            :     }
    1350                 :        525 :     break;
    1351                 :       5788 :     case Kind::SINE:
    1352         [ +  + ]:       5788 :       if (t[0].isConst())
    1353                 :            :       {
    1354                 :       2249 :         const Rational& rat = t[0].getConst<Rational>();
    1355         [ +  + ]:       2249 :         if (rat.sgn() == 0)
    1356                 :            :         {
    1357                 :        116 :           return RewriteResponse(REWRITE_DONE, nm->mkConstReal(Rational(0)));
    1358                 :            :         }
    1359         [ +  + ]:       2191 :         else if (rat.sgn() == -1)
    1360                 :            :         {
    1361                 :            :           Node ret = nm->mkNode(Kind::NEG,
    1362                 :        394 :                                 nm->mkNode(Kind::SINE, nm->mkConstReal(-rat)));
    1363                 :        197 :           return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1364                 :        197 :         }
    1365                 :            :       }
    1366 [ +  + ][ -  - ]:       3539 :       else if ((t[0].getKind() == Kind::MULT
    1367 [ -  + ][ +  - ]:       6988 :                 || t[0].getKind() == Kind::NONLINEAR_MULT)
                 [ -  - ]
    1368                 :       6988 :                && t[0][0].isConst() && t[0][0].getConst<Rational>().sgn() == -1)
    1369                 :            :       {
    1370                 :            :         // sin(-n*x) ---> -sin(n*x)
    1371                 :         30 :         std::vector<Node> mchildren(t[0].begin(), t[0].end());
    1372                 :         15 :         mchildren[0] = nm->mkConstReal(-t[0][0].getConst<Rational>());
    1373                 :            :         Node ret = nm->mkNode(
    1374                 :            :             Kind::NEG,
    1375                 :         30 :             nm->mkNode(Kind::SINE, nm->mkNode(t[0].getKind(), mchildren)));
    1376                 :         15 :         return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1377                 :         15 :       }
    1378                 :            :       else
    1379                 :            :       {
    1380                 :            :         // get the factor of PI in the argument
    1381                 :       3524 :         Node pi_factor;
    1382                 :       3524 :         Node pi;
    1383                 :       3524 :         Node rem;
    1384                 :       3524 :         std::map<Node, Node> msum;
    1385         [ +  - ]:       3524 :         if (ArithMSum::getMonomialSum(t[0], msum))
    1386                 :            :         {
    1387                 :       3524 :           pi = mkPi(nm);
    1388                 :       3524 :           std::map<Node, Node>::iterator itm = msum.find(pi);
    1389         [ +  + ]:       3524 :           if (itm != msum.end())
    1390                 :            :           {
    1391         [ +  + ]:       2083 :             if (itm->second.isNull())
    1392                 :            :             {
    1393                 :         12 :               pi_factor = rewriter::mkConst(d_nm, Integer(1));
    1394                 :            :             }
    1395                 :            :             else
    1396                 :            :             {
    1397                 :       2071 :               pi_factor = itm->second;
    1398                 :            :             }
    1399                 :       2083 :             msum.erase(pi);
    1400         [ +  + ]:       2083 :             if (!msum.empty())
    1401                 :            :             {
    1402                 :       2006 :               rem = ArithMSum::mkNode(nm, msum);
    1403                 :            :             }
    1404                 :            :           }
    1405                 :            :         }
    1406                 :            :         else
    1407                 :            :         {
    1408                 :          0 :           DebugUnhandled();
    1409                 :            :         }
    1410                 :            : 
    1411                 :            :         // if there is a factor of PI
    1412         [ +  + ]:       3524 :         if (!pi_factor.isNull())
    1413                 :            :         {
    1414         [ +  - ]:       4166 :           Trace("arith-tf-rewrite-debug")
    1415                 :       2083 :               << "Process pi factor = " << pi_factor << std::endl;
    1416                 :       2083 :           Rational r = pi_factor.getConst<Rational>();
    1417                 :       2083 :           Rational r_abs = r.abs();
    1418                 :       2083 :           Rational rone = Rational(1);
    1419                 :       2083 :           Rational rtwo = Rational(2);
    1420         [ +  + ]:       2083 :           if (r_abs > rone)
    1421                 :            :           {
    1422                 :            :             // add/substract 2*pi beyond scope
    1423                 :          1 :             Rational ra_div_two = (r_abs + rone) / rtwo;
    1424                 :          1 :             Node new_pi_factor;
    1425         [ +  - ]:          1 :             if (r.sgn() == 1)
    1426                 :            :             {
    1427                 :          1 :               new_pi_factor = nm->mkConstReal(r - rtwo * ra_div_two.floor());
    1428                 :            :             }
    1429                 :            :             else
    1430                 :            :             {
    1431                 :          0 :               Assert(r.sgn() == -1);
    1432                 :          0 :               new_pi_factor = nm->mkConstReal(r + rtwo * ra_div_two.floor());
    1433                 :            :             }
    1434                 :          2 :             Node new_arg = nm->mkNode(Kind::MULT, new_pi_factor, pi);
    1435         [ +  - ]:          1 :             if (!rem.isNull())
    1436                 :            :             {
    1437                 :          1 :               new_arg = nm->mkNode(Kind::ADD, new_arg, rem);
    1438                 :            :             }
    1439                 :          1 :             new_arg = rewriter::ensureReal(new_arg);
    1440                 :            :             // sin( 2*n*PI + x ) = sin( x )
    1441                 :            :             return RewriteResponse(REWRITE_AGAIN_FULL,
    1442                 :          2 :                                    nm->mkNode(Kind::SINE, new_arg));
    1443                 :          1 :           }
    1444         [ +  + ]:       2082 :           else if (r_abs == rone)
    1445                 :            :           {
    1446                 :            :             // sin( PI + x ) = -sin( x )
    1447         [ +  + ]:         12 :             if (rem.isNull())
    1448                 :            :             {
    1449                 :            :               return RewriteResponse(REWRITE_DONE,
    1450                 :          4 :                                      nm->mkConstReal(Rational(0)));
    1451                 :            :             }
    1452                 :            :             else
    1453                 :            :             {
    1454                 :         10 :               rem = rewriter::ensureReal(rem);
    1455                 :            :               return RewriteResponse(
    1456                 :            :                   REWRITE_AGAIN_FULL,
    1457                 :         20 :                   nm->mkNode(Kind::NEG, nm->mkNode(Kind::SINE, rem)));
    1458                 :            :             }
    1459                 :            :           }
    1460         [ +  + ]:       2070 :           else if (rem.isNull())
    1461                 :            :           {
    1462                 :            :             // other rational cases based on Niven's theorem
    1463                 :            :             // (https://en.wikipedia.org/wiki/Niven%27s_theorem)
    1464                 :         75 :             Integer one = Integer(1);
    1465                 :         75 :             Integer two = Integer(2);
    1466                 :         75 :             Integer six = Integer(6);
    1467         [ +  - ]:         75 :             if (r_abs.getDenominator() == two)
    1468                 :            :             {
    1469 [ -  + ][ -  + ]:         75 :               Assert(r_abs.getNumerator() == one);
                 [ -  - ]
    1470                 :            :               return RewriteResponse(REWRITE_DONE,
    1471                 :        150 :                                      nm->mkConstReal(Rational(r.sgn())));
    1472                 :            :             }
    1473         [ -  - ]:          0 :             else if (r_abs.getDenominator() == six)
    1474                 :            :             {
    1475                 :          0 :               Integer five = Integer(5);
    1476                 :          0 :               if (r_abs.getNumerator() == one || r_abs.getNumerator() == five)
    1477                 :            :               {
    1478                 :            :                 return RewriteResponse(
    1479                 :            :                     REWRITE_DONE,
    1480                 :          0 :                     nm->mkConstReal(Rational(r.sgn()) / Rational(2)));
    1481                 :            :               }
    1482         [ -  - ]:          0 :             }
    1483 [ -  + ][ -  + ]:        225 :           }
                 [ -  + ]
    1484 [ +  + ][ +  + ]:       2347 :         }
         [ +  + ][ +  + ]
    1485 [ +  + ][ +  + ]:       3788 :       }
         [ +  + ][ +  + ]
    1486                 :       5430 :       break;
    1487                 :        258 :     case Kind::COSINE:
    1488                 :            :     {
    1489                 :            :       return RewriteResponse(
    1490                 :            :           REWRITE_AGAIN_FULL,
    1491                 :        516 :           nm->mkNode(
    1492                 :            :               Kind::SINE,
    1493                 :       1032 :               nm->mkNode(Kind::SUB,
    1494 [ +  + ][ -  - ]:       1290 :                          nm->mkNode(Kind::MULT,
    1495                 :        516 :                                     {nm->mkConstReal(Rational(1) / Rational(2)),
    1496                 :        516 :                                      mkPi(nm)}),
    1497                 :        258 :                          t[0])));
    1498                 :            :     }
    1499                 :            :     break;
    1500                 :         57 :     case Kind::TANGENT:
    1501                 :            :     {
    1502                 :            :       return RewriteResponse(REWRITE_AGAIN_FULL,
    1503 [ +  + ][ -  - ]:        285 :                              nm->mkNode(Kind::DIVISION,
    1504                 :        114 :                                         {nm->mkNode(Kind::SINE, t[0]),
    1505                 :        171 :                                          nm->mkNode(Kind::COSINE, t[0])}));
    1506                 :            :     }
    1507                 :            :     break;
    1508                 :         20 :     case Kind::COSECANT:
    1509                 :            :     {
    1510                 :            :       return RewriteResponse(REWRITE_AGAIN_FULL,
    1511 [ +  + ][ -  - ]:        100 :                              nm->mkNode(Kind::DIVISION,
    1512                 :         40 :                                         {nm->mkConstReal(Rational(1)),
    1513                 :         60 :                                          nm->mkNode(Kind::SINE, t[0])}));
    1514                 :            :     }
    1515                 :            :     break;
    1516                 :         33 :     case Kind::SECANT:
    1517                 :            :     {
    1518                 :            :       return RewriteResponse(REWRITE_AGAIN_FULL,
    1519 [ +  + ][ -  - ]:        165 :                              nm->mkNode(Kind::DIVISION,
    1520                 :         66 :                                         {nm->mkConstReal(Rational(1)),
    1521                 :         99 :                                          nm->mkNode(Kind::COSINE, t[0])}));
    1522                 :            :     }
    1523                 :            :     break;
    1524                 :         22 :     case Kind::COTANGENT:
    1525                 :            :     {
    1526                 :            :       return RewriteResponse(REWRITE_AGAIN_FULL,
    1527 [ +  + ][ -  - ]:        110 :                              nm->mkNode(Kind::DIVISION,
    1528                 :         44 :                                         {nm->mkNode(Kind::COSINE, t[0]),
    1529                 :         66 :                                          nm->mkNode(Kind::SINE, t[0])}));
    1530                 :            :     }
    1531                 :            :     break;
    1532                 :        338 :     default: break;
    1533                 :            :   }
    1534                 :       6293 :   return RewriteResponse(REWRITE_DONE, t);
    1535                 :            : }
    1536                 :            : 
    1537                 :      46125 : Node ArithRewriter::expandDefinition(Node node)
    1538                 :            : {
    1539                 :            :   // call eliminate operators, to eliminate partial operators only
    1540                 :      46125 :   std::vector<SkolemLemma> lems;
    1541                 :      46125 :   TrustNode ret = d_opElim.eliminate(node, lems, true);
    1542 [ -  + ][ -  + ]:      46125 :   Assert(lems.empty());
                 [ -  - ]
    1543         [ +  + ]:      46125 :   if (ret.isNull())
    1544                 :            :   {
    1545                 :      45926 :     return Node::null();
    1546                 :            :   }
    1547                 :        199 :   return ret.getNode();
    1548                 :      46125 : }
    1549                 :            : 
    1550                 :       8082 : RewriteResponse ArithRewriter::returnRewrite(TNode t, Node ret, Rewrite r)
    1551                 :            : {
    1552         [ +  - ]:      16164 :   Trace("arith-rewriter") << "ArithRewriter : " << t << " == " << ret << " by "
    1553                 :       8082 :                           << r << std::endl;
    1554                 :       8082 :   return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1555                 :            : }
    1556                 :            : 
    1557                 :     223456 : Node ArithRewriter::rewriteIneqToBv(const Node& ineq)
    1558                 :            : {
    1559 [ -  + ][ -  + ]:     223456 :   Assert(ineq.getKind() == Kind::GEQ);
                 [ -  - ]
    1560                 :            : 
    1561                 :     446912 :   Node left = rewriter::removeToReal(ineq[0]);
    1562                 :     446912 :   Node right = rewriter::removeToReal(ineq[1]);
    1563                 :            : 
    1564                 :     223456 :   rewriter::Sum sum;
    1565                 :     223456 :   rewriter::addToSum(sum, left, false);
    1566                 :     223456 :   rewriter::addToSum(sum, right, true);
    1567                 :            : 
    1568                 :     446912 :   return rewriteIneqToBv(Kind::GEQ, sum, ineq);
    1569                 :     223456 : }
    1570                 :            : 
    1571                 :     223456 : Node ArithRewriter::rewriteIneqToBv(Kind kind,
    1572                 :            :                                     const rewriter::Sum& sum,
    1573                 :            :                                     const Node& ineq)
    1574                 :            : {
    1575                 :     223456 :   bool convertible = true;
    1576                 :            :   // the (single) bv2nat term in the sum
    1577                 :     223456 :   Node bv2natTerm;
    1578                 :            :   // whether the bv2nat term is positive in the sum
    1579                 :     223456 :   bool bv2natPol = false;
    1580                 :            :   // the remaining sum (constant)
    1581                 :     223456 :   std::vector<Node> otherSum;
    1582                 :     223456 :   NodeManager* nm = nodeManager();
    1583         [ +  + ]:     361981 :   for (const std::pair<const Node, RealAlgebraicNumber>& m : sum)
    1584                 :            :   {
    1585         [ +  - ]:     361940 :     if (m.second.isRational())
    1586                 :            :     {
    1587                 :     361940 :       const Rational& r = m.second.toRational();
    1588                 :     361940 :       Kind mk = m.first.getKind();
    1589         [ +  + ]:     361940 :       if (mk == Kind::BITVECTOR_UBV_TO_INT)
    1590                 :            :       {
    1591                 :            :         // We currently only eliminate sums involving exactly one
    1592                 :            :         // (bv2nat x) monomial whose coefficient is +- 1, although more
    1593                 :            :         // cases could be handled here.
    1594         [ +  + ]:         47 :         if (bv2natTerm.isNull())
    1595                 :            :         {
    1596         [ +  + ]:         45 :           if (r.abs().isOne())
    1597                 :            :           {
    1598                 :         43 :             bv2natPol = (r.sgn() == 1);
    1599                 :         43 :             bv2natTerm = m.first;
    1600                 :         43 :             continue;
    1601                 :            :           }
    1602                 :            :         }
    1603                 :            :         else
    1604                 :            :         {
    1605                 :          2 :           convertible = false;
    1606                 :          2 :           break;
    1607                 :            :         }
    1608                 :            :       }
    1609 [ +  + ][ +  - ]:     361893 :       else if (mk == Kind::CONST_INTEGER && m.second.isRational())
                 [ +  + ]
    1610                 :            :       {
    1611         [ +  + ]:     148641 :         if (r.isIntegral())
    1612                 :            :         {
    1613                 :     138482 :           otherSum.push_back(nm->mkConstInt(r));
    1614                 :     138482 :           continue;
    1615                 :            :         }
    1616                 :            :       }
    1617                 :            :       // if a non-constant, non-bv2nat term is in the sum, we fail
    1618    [ +  + ][ + ]:     361940 :     }
    1619                 :     223413 :     convertible = false;
    1620                 :     223413 :     break;
    1621                 :            :   }
    1622 [ +  + ][ +  - ]:     223456 :   if (convertible && !bv2natTerm.isNull())
                 [ +  + ]
    1623                 :            :   {
    1624                 :         41 :     Node zero = nm->mkConstInt(Rational(0));
    1625                 :         41 :     Kind bvKind =
    1626                 :            :         (kind == Kind::GT
    1627 [ -  + ][ -  - ]:         82 :              ? (bv2natPol ? Kind::BITVECTOR_UGT : Kind::BITVECTOR_ULT)
    1628         [ +  - ]:         41 :              : (bv2natPol ? Kind::BITVECTOR_UGE : Kind::BITVECTOR_ULE));
    1629                 :         41 :     Node bvt = bv2natTerm[0];
    1630                 :         41 :     size_t bvsize = bvt.getType().getBitVectorSize();
    1631                 :         82 :     Node w = nm->mkConstInt(Rational(Integer(2).pow(bvsize)));
    1632                 :         41 :     Node osum = otherSum.empty()
    1633                 :            :                     ? zero
    1634                 :         40 :                     : (otherSum.size() == 1 ? otherSum[0]
    1635 [ +  + ][ +  - ]:         81 :                                             : nm->mkNode(Kind::ADD, otherSum));
    1636                 :            :     // possibly negate the sum
    1637                 :            :     Node o = bv2natPol
    1638                 :         41 :                  ? (osum.getKind() == Kind::NEG ? osum[0]
    1639                 :            :                                                 : nm->mkNode(Kind::NEG, osum))
    1640 [ +  - ][ -  + ]:         82 :                  : osum;
         [ +  - ][ -  - ]
    1641                 :         82 :     Node ub = nm->mkNode(Kind::GEQ, o, w);
    1642                 :         82 :     Node lb = nm->mkNode(Kind::LT, o, zero);
    1643                 :         41 :     Node iToBvop = nm->mkConst(IntToBitVector(bvsize));
    1644                 :        164 :     Node ret = nm->mkNode(
    1645                 :            :         Kind::ITE,
    1646                 :            :         {ub,
    1647                 :         41 :          nm->mkConst(!bv2natPol),
    1648                 :        328 :          nm->mkNode(
    1649                 :            :              Kind::ITE,
    1650                 :            :              {lb,
    1651                 :         82 :               nm->mkConst(bv2natPol),
    1652                 :         82 :               nm->mkNode(bvKind,
    1653                 :            :                          bvt,
    1654                 :        246 :                          nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, o))})});
    1655                 :            :     // E.g. (<= (bv2nat x) N) -->
    1656                 :            :     //      (ite (>= N 2^w) true (ite (< N 0) false (bvule x ((_ int2bv w) N))
    1657                 :            :     // or   (<= N (bv2nat x)) -->
    1658                 :            :     //      (ite (>= N 2^w) false (ite (< N 0) true (bvuge x ((_ int2bv w) N))
    1659                 :            :     // where N is a constant. Note that ((_ int2bv w) N) will subsequently
    1660                 :            :     // be rewritten to the appropriate bitvector constant.
    1661                 :         41 :     return ret;
    1662                 :         41 :   }
    1663                 :     223415 :   return ineq;
    1664                 :     223456 : }
    1665                 :            : 
    1666                 :        221 : Node ArithRewriter::expandPowConst(NodeManager* nm, const Node& t)
    1667                 :            : {
    1668         [ +  + ]:        221 :   if (t[1].isConst())
    1669                 :            :   {
    1670                 :        213 :     const Rational& exp = t[1].getConst<Rational>();
    1671         [ -  + ]:        213 :     if (!exp.isIntegral())
    1672                 :            :     {
    1673                 :        209 :       return Node::null();
    1674                 :            :     }
    1675                 :        213 :     TNode base = t[0];
    1676         [ +  + ]:        213 :     if (exp.sgn() == 0)
    1677                 :            :     {
    1678                 :         40 :       return nm->mkConstRealOrInt(t.getType(), Rational(1));
    1679                 :            :     }
    1680         [ +  + ]:        193 :     else if (exp.sgn() > 0)
    1681                 :            :     {
    1682                 :        191 :       Rational r(expr::NodeValue::MAX_CHILDREN);
    1683         [ +  + ]:        191 :       if (exp <= r)
    1684                 :            :       {
    1685                 :        189 :         unsigned num = exp.getNumerator().toUnsignedInt();
    1686                 :        189 :         Node ret;
    1687         [ +  + ]:        189 :         if (num == 1)
    1688                 :            :         {
    1689                 :         22 :           ret = base;
    1690                 :            :         }
    1691                 :            :         else
    1692                 :            :         {
    1693                 :        167 :           NodeBuilder nb(nm, Kind::MULT);
    1694         [ +  + ]:        910 :           for (unsigned i = 0; i < num; ++i)
    1695                 :            :           {
    1696                 :        743 :             nb << base;
    1697                 :            :           }
    1698 [ -  + ][ -  + ]:        167 :           Assert(nb.getNumChildren() > 0);
                 [ -  - ]
    1699                 :        167 :           ret = nb;
    1700                 :        167 :         }
    1701                 :        189 :         return ret;
    1702                 :        189 :       }
    1703         [ +  + ]:        191 :     }
    1704         [ +  + ]:        213 :   }
    1705                 :         12 :   return Node::null();
    1706                 :            : }
    1707                 :            : 
    1708                 :            : }  // namespace arith
    1709                 :            : }  // namespace theory
    1710                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14