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: 854 912 93.6 %
Date: 2026-09-09 10:08:49 Functions: 37 38 97.4 %
Branches: 621 934 66.5 %

           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                 :    5378425 : bool flattenAndCollectSum(TNode t,
      62                 :            :                           std::vector<std::pair<TNode, Rational>>& children,
      63                 :            :                           Kinds... kinds)
      64                 :            : {
      65         [ +  + ]:    5378425 :   if (!expr::algorithm::canFlatten(t, kinds...))
      66                 :            :   {
      67                 :    4833610 :     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                 :     544815 :   std::map<TNode, Rational> countMap;
      75                 :     544815 :   countMap[t] = Rational(1);
      76                 :     544815 :   std::map<TNode, Rational>::iterator it;
      77                 :     544815 :   Kind tk = t.getKind();
      78         [ +  + ]:    7879367 :   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                 :    3667276 :     std::map<TNode, Rational>::iterator cur = std::prev(countMap.end());
      83                 :    3667276 :     bool recurse = false;
      84                 :    3667276 :     TNode tc = cur->first;
      85                 :    3667276 :     Kind k = tc.getKind();
      86                 :    3667276 :     Rational coeff = cur->second;
      87                 :    3667276 :     countMap.erase(cur);
      88                 :            :     // Additionally collect coefficient
      89 [ +  + ][ +  - ]:    4643807 :     while (k == Kind::MULT && tc.getNumChildren() == 2 && tc[0].isConst())
         [ +  + ][ +  + ]
         [ +  + ][ -  - ]
      90                 :            :     {
      91                 :     976531 :       coeff *= tc[0].getConst<Rational>();
      92                 :     976531 :       tc = tc[1];
      93                 :     976531 :       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 [ +  + ][ +  + ]:    3667276 :       recurse = ((kinds == k) || ...);
     103                 :            :     }
     104         [ +  + ]:    3667276 :     if (recurse)
     105                 :            :     {
     106         [ +  + ]:    6716576 :       for (TNode cc : tc)
     107                 :            :       {
     108                 :    3541694 :         countMap[cc] += coeff;
     109                 :            :       }
     110                 :            :     }
     111                 :            :     else
     112                 :            :     {
     113                 :    2079835 :       children.emplace_back(tc, coeff);
     114                 :            :     }
     115                 :            :   }
     116                 :     544815 :   return true;
     117                 :     544815 : }
     118                 :            : 
     119                 :      28851 : ArithRewriter::ArithRewriter(NodeManager* nm,
     120                 :            :                              OperatorElim& oe,
     121                 :      28851 :                              bool expertEnabled)
     122                 :      28851 :     : TheoryRewriter(nm), d_opElim(oe), d_expertEnabled(expertEnabled)
     123                 :            : {
     124                 :      28851 :   registerProofRewriteRule(ProofRewriteRule::ARITH_POW_ELIM,
     125                 :            :                            TheoryRewriteCtx::PRE_DSL);
     126                 :      28851 :   registerProofRewriteRule(ProofRewriteRule::MACRO_ARITH_STRING_PRED_ENTAIL,
     127                 :            :                            TheoryRewriteCtx::DSL_SUBCALL);
     128                 :      28851 :   registerProofRewriteRule(ProofRewriteRule::MACRO_ARITH_INT_EQ_CONFLICT,
     129                 :            :                            TheoryRewriteCtx::DSL_SUBCALL);
     130                 :      28851 :   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                 :      28851 : }
     136                 :            : 
     137                 :    2054639 : Node ArithRewriter::rewriteViaRule(ProofRewriteRule id, const Node& n)
     138                 :            : {
     139 [ +  + ][ +  + ]:    2054639 :   switch (id)
                 [ +  + ]
     140                 :            :   {
     141                 :     217998 :     case ProofRewriteRule::ARITH_POW_ELIM:
     142                 :            :     {
     143         [ +  + ]:     217998 :       if (n.getKind() == Kind::POW)
     144                 :            :       {
     145                 :         28 :         Node nx = expandPowConst(nodeManager(), n);
     146         [ +  - ]:         28 :         if (!nx.isNull())
     147                 :            :         {
     148                 :         28 :           return nx;
     149                 :            :         }
     150         [ -  + ]:         28 :       }
     151                 :            :     }
     152                 :     217970 :     break;
     153                 :     613437 :     case ProofRewriteRule::MACRO_ARITH_STRING_PRED_ENTAIL:
     154                 :            :     {
     155                 :            :       // only matters if n contains integer string operators
     156                 :    1134000 :       if (!n.getType().isBoolean() || n.getNumChildren() != 2 || n[0] == n[1]
     157                 :    1134000 :           || !expr::hasSubtermKinds(
     158                 :            :               {Kind::STRING_LENGTH, Kind::STRING_INDEXOF, Kind::STRING_STOI},
     159                 :            :               n))
     160                 :            :       {
     161                 :     501491 :         return Node::null();
     162                 :            :       }
     163         [ +  - ]:     111946 :       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                 :     111946 :       theory::strings::ArithEntail ae(d_nm, nullptr);
     168                 :     111946 :       Node tgt;
     169         [ +  + ]:     111946 :       if (n.getKind() == Kind::EQUAL)
     170                 :            :       {
     171                 :      17859 :         tgt = n;
     172                 :            :       }
     173                 :            :       else
     174                 :            :       {
     175                 :      94087 :         tgt = ae.normalizeGeq(n);
     176                 :            :       }
     177                 :     111946 :       if (tgt.isNull() || !tgt[0].getType().isInteger())
     178                 :            :       {
     179                 :         99 :         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                 :     111847 :       Node nexp = ae.rewriteLengthIntro(tgt);
     184         [ +  - ]:     111847 :       Trace("macro-arith-str-pred") << "...setup to " << nexp << std::endl;
     185                 :            :       // Also must make this a "simple" check (isSimple = true).
     186                 :     111847 :       Node ret = ae.rewritePredViaEntailment(nexp, true);
     187         [ +  - ]:     111847 :       Trace("macro-arith-str-pred") << "...result = " << ret << std::endl;
     188                 :     111847 :       return ret;
     189                 :     111946 :     }
     190                 :            :     break;
     191                 :        218 :     case ProofRewriteRule::ARITH_STRING_PRED_ENTAIL:
     192                 :            :     case ProofRewriteRule::ARITH_STRING_PRED_SAFE_APPROX:
     193                 :            :     {
     194 [ +  - ][ -  + ]:        436 :       if (n.getKind() != Kind::GEQ || !n[1].isConst()
                 [ -  - ]
     195 [ +  - ][ -  + ]:        436 :           || n[1].getConst<Rational>().sgn() != 0)
         [ +  - ][ +  - ]
                 [ -  - ]
     196                 :            :       {
     197                 :          0 :         return Node::null();
     198                 :            :       }
     199         [ +  + ]:        218 :       if (id == ProofRewriteRule::ARITH_STRING_PRED_ENTAIL)
     200                 :            :       {
     201         [ +  - ]:        142 :         if (theory::strings::ArithEntail::checkSimple(n[0]))
     202                 :            :         {
     203                 :        284 :           return nodeManager()->mkConst(true);
     204                 :            :         }
     205                 :            :       }
     206         [ +  - ]:         76 :       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                 :         76 :         theory::strings::ArithEntail ae(nodeManager(), nullptr);
     211                 :            :         // must only use simple checks when computing the approximations
     212                 :         76 :         Node approx = ae.findApprox(n[0], true);
     213         [ +  - ]:         76 :         if (approx != n[0])
     214                 :            :         {
     215         [ +  - ]:        152 :           Trace("arith-rewriter-proof")
     216 [ -  + ][ -  - ]:         76 :               << n[0] << " --> " << approx << " by safe approx" << std::endl;
     217                 :         76 :           return nodeManager()->mkNode(Kind::GEQ, approx, n[1]);
     218                 :            :         }
     219 [ -  + ][ -  + ]:        152 :       }
     220                 :            :     }
     221                 :          0 :     break;
     222                 :     611577 :     case ProofRewriteRule::MACRO_ARITH_INT_EQ_CONFLICT:
     223                 :            :     {
     224                 :     611577 :       if (n.getKind() == Kind::EQUAL && n[0] != n[1])
     225                 :            :       {
     226 [ +  + ][ +  + ]:      91123 :         Node a = n[0].getKind() == Kind::TO_REAL ? n[0][0] : n[0];
                 [ -  - ]
     227 [ +  + ][ +  + ]:      91056 :         Node b = n[1].getKind() == Kind::TO_REAL ? n[1][0] : n[1];
                 [ -  - ]
     228                 :      90825 :         rewriter::Sum sum;
     229                 :            :         // allow dropping TO_REAL
     230                 :      90825 :         rewriter::addToSumNoMixed(sum, a, false);
     231                 :      90825 :         rewriter::addToSumNoMixed(sum, b, true);
     232         [ +  + ]:      90825 :         if (rewriter::isIntegral(sum))
     233                 :            :         {
     234                 :      70483 :           std::pair<Node, Node> p = decomposeSum(d_nm, std::move(sum));
     235                 :      70483 :           Rational c = p.second.getConst<Rational>();
     236         [ +  + ]:      70483 :           if (!c.isIntegral())
     237                 :            :           {
     238                 :        468 :             return d_nm->mkConst(false);
     239                 :            :           }
     240 [ +  + ][ +  + ]:      70717 :         }
     241 [ +  + ][ +  + ]:      91293 :       }
                 [ +  + ]
     242                 :            :     }
     243                 :     611343 :     break;
     244                 :     611404 :     case ProofRewriteRule::MACRO_ARITH_INT_GEQ_TIGHTEN:
     245                 :            :     {
     246         [ +  - ]:     611404 :       Trace("arith-rewriter-proof") << "Rewrite " << n << "?" << std::endl;
     247                 :     611404 :       if (n.getKind() == Kind::GEQ && n[0] != n[1])
     248                 :            :       {
     249 [ +  + ][ +  + ]:     210844 :         Node a = n[0].getKind() == Kind::TO_REAL ? n[0][0] : n[0];
                 [ -  - ]
     250 [ +  + ][ +  + ]:     210727 :         Node b = n[1].getKind() == Kind::TO_REAL ? n[1][0] : n[1];
                 [ -  - ]
     251                 :     210560 :         rewriter::Sum sum;
     252                 :            :         // allow dropping TO_REAL
     253                 :     210560 :         rewriter::addToSumNoMixed(sum, a, false);
     254                 :     210560 :         rewriter::addToSumNoMixed(sum, b, true);
     255         [ +  + ]:     210560 :         if (rewriter::isIntegral(sum))
     256                 :            :         {
     257                 :            :           // decompose the sum into a non-constant and constant part
     258                 :     171541 :           bool negated = false;
     259                 :            :           std::pair<Node, Node> p =
     260                 :     171541 :               decomposeSum(d_nm, std::move(sum), negated, true);
     261                 :     171541 :           Rational c = p.second.getConst<Rational>();
     262         [ +  - ]:     343082 :           Trace("arith-rewriter-proof")
     263                 :     171541 :               << "Decomposed to " << p.first << " + " << p.second << std::endl;
     264         [ +  + ]:     171541 :           if (!c.isIntegral())
     265                 :            :           {
     266                 :        177 :             c = -c;
     267                 :        177 :             c = c.ceiling();
     268                 :        354 :             Node ret = d_nm->mkNode(Kind::GEQ, p.first, d_nm->mkConstInt(c));
     269         [ +  + ]:        177 :             if (negated)
     270                 :            :             {
     271                 :         83 :               ret = ret.notNode();
     272                 :            :             }
     273                 :        177 :             return ret;
     274                 :        177 :           }
     275 [ +  + ][ +  + ]:     171718 :         }
     276 [ +  + ][ +  + ]:     210914 :       }
                 [ +  + ]
     277                 :            :     }
     278                 :     611227 :     break;
     279                 :          5 :     default: break;
     280                 :            :   }
     281                 :    1440545 :   return Node::null();
     282                 :            : }
     283                 :            : 
     284                 :   12811500 : RewriteResponse ArithRewriter::preRewrite(TNode t)
     285                 :            : {
     286         [ +  - ]:   12811500 :   Trace("arith-rewriter") << "preRewrite(" << t << ")" << std::endl;
     287         [ +  + ]:   12811500 :   if (rewriter::isAtom(t))
     288                 :            :   {
     289                 :    6776329 :     auto res = preRewriteAtom(t);
     290         [ +  - ]:   13552658 :     Trace("arith-rewriter")
     291                 :    6776329 :         << res.d_status << " -> " << res.d_node << std::endl;
     292                 :    6776329 :     return res;
     293                 :    6776329 :   }
     294                 :    6035171 :   auto res = preRewriteTerm(t);
     295         [ +  - ]:    6035171 :   Trace("arith-rewriter") << res.d_status << " -> " << res.d_node << std::endl;
     296                 :    6035171 :   return res;
     297                 :    6035171 : }
     298                 :            : 
     299                 :   10940956 : RewriteResponse ArithRewriter::postRewrite(TNode t)
     300                 :            : {
     301         [ +  - ]:   10940956 :   Trace("arith-rewriter") << "postRewrite(" << t << ")" << std::endl;
     302         [ +  + ]:   10940956 :   if (rewriter::isAtom(t))
     303                 :            :   {
     304                 :    5706688 :     auto res = postRewriteAtom(t);
     305         [ +  - ]:   11413376 :     Trace("arith-rewriter")
     306                 :    5706688 :         << res.d_status << " -> " << res.d_node << std::endl;
     307                 :    5706688 :     return res;
     308                 :    5706688 :   }
     309                 :    5234268 :   auto res = postRewriteTerm(t);
     310         [ +  - ]:    5234268 :   Trace("arith-rewriter") << res.d_status << " -> " << res.d_node << std::endl;
     311                 :    5234268 :   return res;
     312                 :    5234268 : }
     313                 :            : 
     314                 :    6776329 : RewriteResponse ArithRewriter::preRewriteAtom(TNode atom)
     315                 :            : {
     316 [ -  + ][ -  + ]:    6776329 :   Assert(rewriter::isAtom(atom));
                 [ -  - ]
     317                 :            : 
     318                 :    6776329 :   Kind kind = atom.getKind();
     319         [ +  + ]:    6776329 :   if (atom.getNumChildren() == 2)
     320                 :            :   {
     321         [ +  + ]:    6775380 :     if (auto response =
     322                 :    6775380 :             rewriter::tryEvaluateRelationReflexive(kind, atom[0], atom[1]);
     323                 :    6775380 :         response)
     324                 :            :     {
     325                 :     198856 :       return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, *response));
     326                 :            :     }
     327                 :            :   }
     328                 :            : 
     329 [ +  + ][ +  + ]:    6676901 :   switch (kind)
                    [ + ]
     330                 :            :   {
     331                 :     250515 :     case Kind::GT:
     332                 :            :       return RewriteResponse(
     333                 :            :           REWRITE_DONE,
     334                 :     501030 :           rewriter::buildRelation(Kind::LEQ, atom[0], atom[1], true));
     335                 :     242511 :     case Kind::LT:
     336                 :            :       return RewriteResponse(
     337                 :            :           REWRITE_DONE,
     338                 :     485022 :           rewriter::buildRelation(Kind::GEQ, atom[0], atom[1], true));
     339                 :        871 :     case Kind::IS_INTEGER:
     340         [ +  + ]:        871 :       if (atom[0].getType().isInteger())
     341                 :            :       {
     342                 :         10 :         return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, true));
     343                 :            :       }
     344                 :        866 :       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                 :    6183870 :     default:;
     352                 :            :   }
     353                 :            : 
     354                 :    6183870 :   return RewriteResponse(REWRITE_DONE, atom);
     355                 :            : }
     356                 :            : 
     357                 :    5706688 : RewriteResponse ArithRewriter::postRewriteAtom(TNode atom)
     358                 :            : {
     359 [ -  + ][ -  + ]:    5706688 :   Assert(rewriter::isAtom(atom));
                 [ -  - ]
     360         [ +  - ]:    5706688 :   Trace("arith-rewriter") << "postRewriteAtom: " << atom << std::endl;
     361                 :            : 
     362         [ +  + ]:    5706688 :   if (atom.getKind() == Kind::IS_INTEGER)
     363                 :            :   {
     364                 :        832 :     return rewriteExtIntegerOp(atom);
     365                 :            :   }
     366         [ +  + ]:    5705856 :   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                 :    5705817 :   Kind kind = atom.getKind();
     389                 :   11411634 :   Node left = rewriter::removeToReal(atom[0]);
     390                 :   11411634 :   Node right = rewriter::removeToReal(atom[1]);
     391                 :            : 
     392         [ +  + ]:   11411634 :   if (auto response = rewriter::tryEvaluateRelationReflexive(kind, left, right);
     393                 :    5705817 :       response)
     394                 :            :   {
     395                 :     360526 :     return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, *response));
     396                 :            :   }
     397                 :            : 
     398 [ -  + ][ -  + ]:    5525554 :   Assert(isRelationOperator(kind));
                 [ -  - ]
     399                 :            : 
     400         [ +  + ]:   11051108 :   if (auto response = rewriter::tryEvaluateRelation(kind, left, right);
     401                 :    5525554 :       response)
     402                 :            :   {
     403                 :    1049270 :     return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, *response));
     404                 :            :   }
     405                 :            : 
     406         [ +  + ]:    5000919 :   if (kind == Kind::EQUAL)
     407                 :            :   {
     408                 :            :     // We do not normalize equalities here, since this does not preserve their
     409                 :            :     // terms, see rewriter::normalizeEquality. However, if the normal form of
     410                 :            :     // the equality is a Boolean constant, we return that constant, which e.g.
     411                 :            :     // is the case for (= (* 2 x) 1) for integer x. This ensures that the
     412                 :            :     // rewritten form of an equality is a Boolean constant whenever it is
     413                 :            :     // equivalent to one, which is relied upon e.g. when setting up atoms in
     414                 :            :     // the linear solver.
     415                 :    2141180 :     bool negated = false;
     416                 :    2141180 :     Node norm = rewriter::normalizeEquality(d_nm, atom, &negated);
     417         [ +  + ]:    2141180 :     if (norm.isConst())
     418                 :            :     {
     419                 :       7132 :       return RewriteResponse(REWRITE_DONE, norm);
     420                 :            :     }
     421                 :            :     // Otherwise, we only orient the equality, which we do so that it points in
     422                 :            :     // the same direction as its normal form, i.e. so that the difference of
     423                 :            :     // its sides is a positive multiple of the difference of the sides of norm.
     424                 :            :     // Note this makes the normal form of an equality itself in rewritten form,
     425                 :            :     // which ensures that the linear solver does not have to introduce a second
     426                 :            :     // atom for an equality that is already in normal form, see
     427                 :            :     // TheoryArithPrivate::setupAtom.
     428         [ +  + ]:    2134048 :     if (negated)
     429                 :            :     {
     430                 :            :       return RewriteResponse(REWRITE_DONE,
     431                 :     725440 :                              d_nm->mkNode(Kind::EQUAL, atom[1], atom[0]));
     432                 :            :     }
     433                 :    1771328 :     return RewriteResponse(REWRITE_DONE, atom);
     434                 :    2141180 :   }
     435                 :            : 
     436                 :            :   // Equalities were handled above, hence the atom is an inequality here.
     437 [ -  + ][ -  + ]:    2859739 :   Assert(kind != Kind::EQUAL);
                 [ -  - ]
     438                 :    2859739 :   bool negate = false;
     439                 :            : 
     440    [ +  - ][ + ]:    2859739 :   switch (atom.getKind())
     441                 :            :   {
     442                 :     324504 :     case Kind::LEQ:
     443                 :     324504 :       kind = Kind::GEQ;
     444                 :     324504 :       negate = true;
     445                 :     324504 :       break;
     446                 :          0 :     case Kind::LT:
     447                 :          0 :       kind = Kind::GT;
     448                 :          0 :       negate = true;
     449                 :          0 :       break;
     450                 :    2535235 :     default: break;
     451                 :            :   }
     452                 :            : 
     453                 :    5719478 :   rewriter::Sum sum;
     454                 :    2859739 :   rewriter::addToSum(sum, left, negate);
     455                 :    2859739 :   rewriter::addToSum(sum, right, !negate);
     456                 :            : 
     457                 :            :   // Now we have (sum <kind> 0)
     458         [ +  + ]:    2859739 :   if (rewriter::isIntegral(sum))
     459                 :            :   {
     460         [ +  - ]:    1782129 :     Trace("arith-rewriter") << "...sum is integral" << std::endl;
     461                 :            :     return RewriteResponse(
     462                 :            :         REWRITE_DONE,
     463                 :    3564258 :         rewriter::buildIntegerInequality(d_nm, std::move(sum), kind));
     464                 :            :   }
     465                 :            :   else
     466                 :            :   {
     467         [ +  - ]:    1077610 :     Trace("arith-rewriter") << "...sum is not integral" << std::endl;
     468                 :            :     return RewriteResponse(
     469                 :            :         REWRITE_DONE,
     470                 :    2155220 :         rewriter::buildRealInequality(d_nm, std::move(sum), kind));
     471                 :            :   }
     472                 :    5705817 : }
     473                 :            : 
     474                 :      43773 : Node ArithRewriter::rewriteEqualityExt(Node node)
     475                 :            : {
     476 [ -  + ][ -  + ]:      43773 :   Assert(node.getKind() == Kind::EQUAL);
                 [ -  - ]
     477         [ -  + ]:      43773 :   if (!node[0].getType().isRealOrInt())
     478                 :            :   {
     479                 :          0 :     return node;
     480                 :            :   }
     481                 :      43773 :   return rewriter::normalizeEquality(d_nm, node);
     482                 :            : }
     483                 :            : 
     484                 :    6035171 : RewriteResponse ArithRewriter::preRewriteTerm(TNode t)
     485                 :            : {
     486         [ +  + ]:    6035171 :   if (t.isConst())
     487                 :            :   {
     488                 :     821923 :     return RewriteResponse(REWRITE_DONE, t);
     489                 :            :   }
     490         [ -  + ]:    5213248 :   else if (t.isVar())
     491                 :            :   {
     492                 :          0 :     return rewriteVariable(t);
     493                 :            :   }
     494                 :            :   else
     495                 :            :   {
     496 [ +  + ][ +  + ]:    5213248 :     switch (Kind k = t.getKind())
         [ +  + ][ +  + ]
            [ +  + ][ - ]
     497                 :            :     {
     498                 :        229 :       case Kind::REAL_ALGEBRAIC_NUMBER: return rewriteRAN(t);
     499                 :     599742 :       case Kind::SUB: return rewriteSub(t);
     500                 :      23677 :       case Kind::NEG: return rewriteNeg(t, true);
     501                 :      10955 :       case Kind::DIVISION:
     502                 :      10955 :       case Kind::DIVISION_TOTAL: return rewriteDiv(t, true);
     503                 :    3134134 :       case Kind::ADD: return preRewritePlus(t);
     504                 :    1360102 :       case Kind::MULT:
     505                 :    1360102 :       case Kind::NONLINEAR_MULT: return preRewriteMult(t);
     506                 :       8518 :       case Kind::INTS_DIVISION:
     507                 :       8518 :       case Kind::INTS_MODULUS: return rewriteIntsDivMod(t);
     508                 :      28504 :       case Kind::INTS_DIVISION_TOTAL:
     509                 :      28504 :       case Kind::INTS_MODULUS_TOTAL: return rewriteIntsDivModTotal(t, true);
     510                 :       6939 :       case Kind::ABS: return rewriteAbs(t);
     511                 :      40448 :       case Kind::IAND:
     512                 :            :       case Kind::PIAND:
     513                 :            :       case Kind::POW2:
     514                 :            :       case Kind::INTS_ISPOW2:
     515                 :            :       case Kind::INTS_LOG2:
     516                 :            :       case Kind::EXPONENTIAL:
     517                 :            :       case Kind::SINE:
     518                 :            :       case Kind::COSINE:
     519                 :            :       case Kind::TANGENT:
     520                 :            :       case Kind::COSECANT:
     521                 :            :       case Kind::SECANT:
     522                 :            :       case Kind::COTANGENT:
     523                 :            :       case Kind::ARCSINE:
     524                 :            :       case Kind::ARCCOSINE:
     525                 :            :       case Kind::ARCTANGENT:
     526                 :            :       case Kind::ARCCOSECANT:
     527                 :            :       case Kind::ARCSECANT:
     528                 :            :       case Kind::ARCCOTANGENT:
     529                 :            :       case Kind::SQRT:
     530                 :            :       case Kind::IS_INTEGER:
     531                 :            :       case Kind::TO_INTEGER:
     532                 :            :       case Kind::TO_REAL:
     533                 :            :       case Kind::POW:
     534                 :      40448 :       case Kind::PI: return RewriteResponse(REWRITE_DONE, t);
     535                 :          0 :       default: Unhandled() << k;
     536                 :            :     }
     537                 :            :   }
     538                 :            : }
     539                 :            : 
     540                 :    5234268 : RewriteResponse ArithRewriter::postRewriteTerm(TNode t)
     541                 :            : {
     542         [ +  + ]:    5234268 :   if (t.isConst())
     543                 :            :   {
     544                 :    1787035 :     return RewriteResponse(REWRITE_DONE, t);
     545                 :            :   }
     546         [ -  + ]:    3447233 :   else if (t.isVar())
     547                 :            :   {
     548                 :          0 :     return rewriteVariable(t);
     549                 :            :   }
     550                 :            :   else
     551                 :            :   {
     552         [ +  - ]:    3447233 :     Trace("arith-rewriter") << "postRewriteTerm: " << t << std::endl;
     553 [ +  - ][ -  + ]:    3447233 :     switch (t.getKind())
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  - ]
     554                 :            :     {
     555                 :        350 :       case Kind::REAL_ALGEBRAIC_NUMBER: return rewriteRAN(t);
     556                 :          0 :       case Kind::SUB: return rewriteSub(t);
     557                 :          0 :       case Kind::NEG: return rewriteNeg(t, false);
     558                 :       5589 :       case Kind::DIVISION:
     559                 :       5589 :       case Kind::DIVISION_TOTAL: return rewriteDiv(t, false);
     560                 :    2244291 :       case Kind::ADD: return postRewritePlus(t);
     561                 :    1117602 :       case Kind::MULT:
     562                 :    1117602 :       case Kind::NONLINEAR_MULT: return postRewriteMult(t);
     563                 :        136 :       case Kind::INTS_ISPOW2: return postRewriteIntsIsPow2(t);
     564                 :        209 :       case Kind::INTS_LOG2: return postRewriteIntsLog2(t);
     565                 :       6843 :       case Kind::INTS_DIVISION:
     566                 :       6843 :       case Kind::INTS_MODULUS: return rewriteIntsDivMod(t);
     567                 :      23236 :       case Kind::INTS_DIVISION_TOTAL:
     568                 :      23236 :       case Kind::INTS_MODULUS_TOTAL: return rewriteIntsDivModTotal(t, false);
     569                 :       6620 :       case Kind::ABS: return rewriteAbs(t);
     570                 :      24357 :       case Kind::TO_REAL: return rewriteToReal(t);
     571                 :       4396 :       case Kind::TO_INTEGER: return rewriteExtIntegerOp(t);
     572                 :        915 :       case Kind::PI: return RewriteResponse(REWRITE_DONE, t);
     573                 :       1982 :       case Kind::POW2: return postRewritePow2(t);
     574                 :        775 :       case Kind::PIAND: return postRewritePIAnd(t);
     575                 :            :       // expert cases
     576                 :       9932 :       case Kind::POW:
     577                 :            :       case Kind::EXPONENTIAL:
     578                 :            :       case Kind::SINE:
     579                 :            :       case Kind::COSINE:
     580                 :            :       case Kind::TANGENT:
     581                 :            :       case Kind::COSECANT:
     582                 :            :       case Kind::SECANT:
     583                 :            :       case Kind::COTANGENT:
     584                 :            :       case Kind::ARCSINE:
     585                 :            :       case Kind::ARCCOSINE:
     586                 :            :       case Kind::ARCTANGENT:
     587                 :            :       case Kind::ARCCOSECANT:
     588                 :            :       case Kind::ARCSECANT:
     589                 :            :       case Kind::ARCCOTANGENT:
     590                 :            :       case Kind::SQRT:
     591                 :       9932 :       case Kind::IAND: return postRewriteExpert(t);
     592                 :          0 :       default: Unreachable();
     593                 :            :     }
     594                 :            :   }
     595                 :            : }
     596                 :       9932 : RewriteResponse ArithRewriter::postRewriteExpert(TNode t)
     597                 :            : {
     598         [ -  + ]:       9932 :   if (!d_expertEnabled)
     599                 :            :   {
     600                 :          0 :     return RewriteResponse(REWRITE_DONE, t);
     601                 :            :   }
     602 [ +  + ][ +  - ]:       9932 :   switch (t.getKind())
     603                 :            :   {
     604                 :        222 :     case Kind::POW:
     605                 :            :     {
     606                 :        222 :       Node tx = expandPowConst(nodeManager(), t);
     607         [ +  + ]:        222 :       if (!tx.isNull())
     608                 :            :       {
     609                 :        210 :         return RewriteResponse(REWRITE_AGAIN_FULL, tx);
     610                 :            :       }
     611                 :         12 :       return RewriteResponse(REWRITE_DONE, t);
     612                 :        222 :     }
     613                 :       7960 :     case Kind::EXPONENTIAL:
     614                 :            :     case Kind::SINE:
     615                 :            :     case Kind::COSINE:
     616                 :            :     case Kind::TANGENT:
     617                 :            :     case Kind::COSECANT:
     618                 :            :     case Kind::SECANT:
     619                 :            :     case Kind::COTANGENT:
     620                 :            :     case Kind::ARCSINE:
     621                 :            :     case Kind::ARCCOSINE:
     622                 :            :     case Kind::ARCTANGENT:
     623                 :            :     case Kind::ARCCOSECANT:
     624                 :            :     case Kind::ARCSECANT:
     625                 :            :     case Kind::ARCCOTANGENT:
     626                 :       7960 :     case Kind::SQRT: return postRewriteTranscendental(t);
     627                 :       1750 :     case Kind::IAND: return postRewriteIAnd(t);
     628                 :          0 :     default: Unreachable();
     629                 :            :   }
     630                 :            : }
     631                 :            : 
     632                 :        579 : RewriteResponse ArithRewriter::rewriteRAN(TNode t)
     633                 :            : {
     634 [ -  + ][ -  + ]:        579 :   Assert(rewriter::isRAN(t));
                 [ -  - ]
     635 [ -  + ][ -  + ]:        579 :   Assert(t.getType().isReal());
                 [ -  - ]
     636                 :        579 :   const RealAlgebraicNumber& r = rewriter::getRAN(t);
     637         [ -  + ]:        579 :   if (r.isRational())
     638                 :            :   {
     639                 :            :     return RewriteResponse(REWRITE_DONE,
     640                 :          0 :                            rewriter::mkConst(d_nm, r.toRational()));
     641                 :            :   }
     642                 :        579 :   return RewriteResponse(REWRITE_DONE, t);
     643                 :            : }
     644                 :            : 
     645                 :          0 : RewriteResponse ArithRewriter::rewriteVariable(TNode t)
     646                 :            : {
     647                 :          0 :   Assert(t.isVar());
     648                 :            : 
     649                 :          0 :   return RewriteResponse(REWRITE_DONE, t);
     650                 :            : }
     651                 :            : 
     652                 :      23677 : RewriteResponse ArithRewriter::rewriteNeg(TNode t, bool pre)
     653                 :            : {
     654 [ -  + ][ -  + ]:      23677 :   Assert(t.getKind() == Kind::NEG);
                 [ -  - ]
     655                 :            : 
     656                 :      23677 :   NodeManager* nm = nodeManager();
     657         [ +  + ]:      23677 :   if (t[0].isConst())
     658                 :            :   {
     659                 :      11016 :     Rational neg = -(t[0].getConst<Rational>());
     660                 :            :     return RewriteResponse(REWRITE_DONE,
     661                 :      22032 :                            nm->mkConstRealOrInt(t.getType(), neg));
     662                 :      11016 :   }
     663         [ +  + ]:      12661 :   if (rewriter::isRAN(t[0]))
     664                 :            :   {
     665                 :            :     return RewriteResponse(REWRITE_DONE,
     666                 :          4 :                            rewriter::mkConst(d_nm, -rewriter::getRAN(t[0])));
     667                 :            :   }
     668                 :            : 
     669                 :            :   Node noUminus =
     670                 :      25318 :       nm->mkNode(Kind::MULT, rewriter::mkConst(d_nm, Rational(-1)), t[0]);
     671         [ +  - ]:      12659 :   if (pre)
     672                 :            :   {
     673                 :      12659 :     return RewriteResponse(REWRITE_DONE, noUminus);
     674                 :            :   }
     675                 :            :   else
     676                 :            :   {
     677                 :          0 :     return RewriteResponse(REWRITE_AGAIN, noUminus);
     678                 :            :   }
     679                 :      12659 : }
     680                 :            : 
     681                 :     599742 : RewriteResponse ArithRewriter::rewriteSub(TNode t)
     682                 :            : {
     683 [ -  + ][ -  + ]:     599742 :   Assert(t.getKind() == Kind::SUB);
                 [ -  - ]
     684 [ -  + ][ -  + ]:     599742 :   Assert(t.getNumChildren() == 2);
                 [ -  - ]
     685                 :            : 
     686                 :     599742 :   NodeManager* nm = nodeManager();
     687         [ +  + ]:     599742 :   if (t[0] == t[1])
     688                 :            :   {
     689                 :            :     return RewriteResponse(REWRITE_DONE,
     690                 :       3330 :                            nm->mkConstRealOrInt(t.getType(), Rational(0)));
     691                 :            :   }
     692                 :            :   return RewriteResponse(
     693                 :            :       REWRITE_AGAIN_FULL,
     694                 :    1196154 :       nm->mkNode(Kind::ADD,
     695                 :            :                  t[0],
     696                 :    2392308 :                  nm->mkNode(Kind::MULT,
     697                 :    1196154 :                             nm->mkConstRealOrInt(t[1].getType(), Rational(-1)),
     698                 :     598077 :                             t[1])));
     699                 :            : }
     700                 :            : 
     701                 :    3134134 : RewriteResponse ArithRewriter::preRewritePlus(TNode t)
     702                 :            : {
     703 [ -  + ][ -  + ]:    3134134 :   Assert(t.getKind() == Kind::ADD);
                 [ -  - ]
     704                 :    3134134 :   std::vector<std::pair<TNode, Rational>> children;
     705         [ +  + ]:    3134134 :   if (!flattenAndCollectSum(t, children, Kind::ADD))
     706                 :            :   {
     707                 :    2757847 :     return RewriteResponse(REWRITE_DONE, t);
     708                 :            :   }
     709                 :     376287 :   NodeManager* nm = nodeManager();
     710                 :     376287 :   NodeBuilder nb(nm, Kind::ADD);
     711                 :     376287 :   Rational coeff(0);
     712         [ +  + ]:    1827396 :   for (const std::pair<TNode, Rational>& c : children)
     713                 :            :   {
     714         [ +  + ]:    1451109 :     if (c.first.isConst())
     715                 :            :     {
     716                 :     572416 :       coeff += c.first.getConst<Rational>() * c.second;
     717                 :            :     }
     718         [ +  + ]:     878693 :     else if (c.second.isOne())
     719                 :            :     {
     720                 :     222334 :       nb << c.first;
     721                 :            :     }
     722                 :            :     else
     723                 :            :     {
     724                 :     656359 :       nb << nm->mkNode(Kind::MULT, nm->mkConstRealOrInt(c.second), c.first);
     725                 :            :     }
     726                 :            :   }
     727 [ +  + ][ +  + ]:     376287 :   if (!coeff.isZero() || nb.getNumChildren() == 0)
                 [ +  + ]
     728                 :            :   {
     729                 :     286437 :     nb << nm->mkConstRealOrInt(t.getType(), coeff);
     730                 :            :   }
     731         [ +  + ]:     376287 :   Node ret = nb.getNumChildren() == 1 ? nb.getChild(0) : nb;
     732                 :     376287 :   ret = rewriter::maybeEnsureReal(t.getType(), ret);
     733                 :     376287 :   return RewriteResponse(REWRITE_DONE, ret);
     734                 :    3134134 : }
     735                 :            : 
     736                 :    2244291 : RewriteResponse ArithRewriter::postRewritePlus(TNode t)
     737                 :            : {
     738 [ -  + ][ -  + ]:    2244291 :   Assert(t.getKind() == Kind::ADD);
                 [ -  - ]
     739 [ -  + ][ -  + ]:    2244291 :   Assert(t.getNumChildren() > 1);
                 [ -  - ]
     740                 :            : 
     741                 :    2244291 :   rewriter::Sum sum;
     742                 :    2244291 :   std::vector<std::pair<TNode, Rational>> children;
     743         [ +  + ]:    2244291 :   if (!flattenAndCollectSum(t, children, Kind::ADD, Kind::TO_REAL))
     744                 :            :   {
     745                 :    2075763 :     rewriter::addToSum(sum, t);
     746                 :            :   }
     747                 :            :   else
     748                 :            :   {
     749                 :     168528 :     Rational coeff(0);
     750         [ +  + ]:     797254 :     for (const std::pair<TNode, Rational>& c : children)
     751                 :            :     {
     752         [ +  + ]:     628726 :       if (c.first.isConst())
     753                 :            :       {
     754                 :     237304 :         coeff += c.first.getConst<Rational>() * c.second;
     755                 :            :       }
     756         [ +  + ]:     391422 :       else if (c.second.isOne())
     757                 :            :       {
     758                 :     143106 :         rewriter::addToSum(sum, c.first);
     759                 :            :       }
     760                 :            :       else
     761                 :            :       {
     762                 :     248316 :         RealAlgebraicNumber mul = RealAlgebraicNumber(c.second);
     763                 :     248316 :         rewriter::addMonomialToSum(sum, c.first, mul);
     764                 :     248316 :       }
     765                 :            :     }
     766         [ +  + ]:     168528 :     if (!coeff.isZero())
     767                 :            :     {
     768                 :     115462 :       rewriter::addToSum(sum, nodeManager()->mkConstRealOrInt(coeff));
     769                 :            :     }
     770                 :     168528 :   }
     771                 :    2244291 :   Node retSum = rewriter::collectSum(d_nm, sum);
     772                 :    2244291 :   retSum = rewriter::maybeEnsureReal(t.getType(), retSum);
     773                 :    4488582 :   return RewriteResponse(REWRITE_DONE, retSum);
     774                 :    2244291 : }
     775                 :            : 
     776                 :    1360102 : RewriteResponse ArithRewriter::preRewriteMult(TNode node)
     777                 :            : {
     778 [ +  + ][ +  - ]:    1360102 :   Assert(node.getKind() == Kind::MULT
         [ -  + ][ -  + ]
                 [ -  - ]
     779                 :            :          || node.getKind() == Kind::NONLINEAR_MULT);
     780                 :            : 
     781         [ +  + ]:    1360102 :   if (auto res = rewriter::getZeroChild(node); res)
     782                 :            :   {
     783                 :            :     return RewriteResponse(REWRITE_DONE,
     784                 :     244972 :                            rewriter::maybeEnsureReal(node.getType(), *res));
     785         [ +  + ]:    1360102 :   }
     786                 :    1237616 :   return RewriteResponse(REWRITE_DONE, node);
     787                 :            : }
     788                 :            : 
     789                 :    1117602 : RewriteResponse ArithRewriter::postRewriteMult(TNode t)
     790                 :            : {
     791 [ +  + ][ +  - ]:    1117602 :   Assert(t.getKind() == Kind::MULT || t.getKind() == Kind::NONLINEAR_MULT);
         [ -  + ][ -  + ]
                 [ -  - ]
     792 [ -  + ][ -  + ]:    1117602 :   Assert(t.getNumChildren() >= 2);
                 [ -  - ]
     793                 :            : 
     794                 :    1117602 :   std::vector<TNode> children;
     795                 :    1117602 :   expr::algorithm::flatten(
     796                 :            :       t, children, Kind::MULT, Kind::NONLINEAR_MULT, Kind::TO_REAL);
     797                 :            : 
     798         [ +  + ]:    1117602 :   if (auto res = rewriter::getZeroChild(children); res)
     799                 :            :   {
     800                 :            :     return RewriteResponse(REWRITE_DONE,
     801                 :      14562 :                            rewriter::maybeEnsureReal(t.getType(), *res));
     802         [ +  + ]:    1117602 :   }
     803                 :            : 
     804                 :    1110321 :   RewriteStatus rs = REWRITE_DONE;
     805                 :    1110321 :   Node ret;
     806                 :            :   // Distribute over addition
     807         [ +  + ]:    1110321 :   if (std::any_of(children.begin(), children.end(), [](TNode child) {
     808                 :    2504419 :         return child.getKind() == Kind::ADD;
     809                 :            :       }))
     810                 :            :   {
     811                 :            :     // if we distribute multiplication, we rewrite again to ensure the
     812                 :            :     // sum is sorted.
     813                 :      72905 :     rs = REWRITE_AGAIN_FULL;
     814                 :      72905 :     ret = rewriter::distributeMultiplication(d_nm, children);
     815                 :            :   }
     816                 :            :   else
     817                 :            :   {
     818                 :    1037416 :     RealAlgebraicNumber ran = RealAlgebraicNumber(Integer(1));
     819                 :    1037416 :     std::vector<Node> leafs;
     820                 :            : 
     821         [ +  + ]:    3398338 :     for (const auto& child : children)
     822                 :            :     {
     823         [ +  + ]:    2360922 :       if (child.isConst())
     824                 :            :       {
     825         [ -  + ]:    1121405 :         if (child.getConst<Rational>().isZero())
     826                 :            :         {
     827                 :            :           return RewriteResponse(REWRITE_DONE,
     828                 :          0 :                                  rewriter::maybeEnsureReal(t.getType(), child));
     829                 :            :         }
     830                 :    1121405 :         ran *= child.getConst<Rational>();
     831                 :            :       }
     832         [ +  + ]:    1239517 :       else if (rewriter::isRAN(child))
     833                 :            :       {
     834                 :        127 :         ran *= rewriter::getRAN(child);
     835                 :            :       }
     836                 :            :       else
     837                 :            :       {
     838                 :    1239390 :         leafs.emplace_back(child);
     839                 :            :       }
     840                 :            :     }
     841                 :    1037416 :     ret = rewriter::mkMultTerm(d_nm, ran, std::move(leafs));
     842 [ +  - ][ +  - ]:    1037416 :   }
     843                 :    1110321 :   ret = rewriter::maybeEnsureReal(t.getType(), ret);
     844                 :    1110321 :   return RewriteResponse(rs, ret);
     845                 :    1117602 : }
     846                 :            : 
     847                 :      16544 : RewriteResponse ArithRewriter::rewriteDiv(TNode t, bool pre)
     848                 :            : {
     849 [ +  + ][ +  - ]:      16544 :   Assert(t.getKind() == Kind::DIVISION_TOTAL || t.getKind() == Kind::DIVISION);
         [ -  + ][ -  + ]
                 [ -  - ]
     850 [ -  + ][ -  + ]:      16544 :   Assert(t.getNumChildren() == 2);
                 [ -  - ]
     851                 :            : 
     852                 :      33088 :   Node left = rewriter::removeToReal(t[0]);
     853                 :      33088 :   Node right = rewriter::removeToReal(t[1]);
     854                 :      16544 :   NodeManager* nm = nodeManager();
     855         [ +  + ]:      16544 :   if (right.isConst())
     856                 :            :   {
     857                 :       6528 :     const Rational& den = right.getConst<Rational>();
     858                 :            : 
     859         [ +  + ]:       6528 :     if (den.isZero())
     860                 :            :     {
     861         [ +  + ]:       1185 :       if (t.getKind() == Kind::DIVISION_TOTAL)
     862                 :            :       {
     863                 :        169 :         Node ret = nm->mkConstReal(0);
     864                 :        169 :         return RewriteResponse(REWRITE_DONE, ret);
     865                 :        169 :       }
     866                 :            :       else
     867                 :            :       {
     868                 :       2032 :         Node ret = nm->mkNode(t.getKind(), left, right);
     869                 :       1016 :         return RewriteResponse(REWRITE_DONE, ret);
     870                 :       1016 :       }
     871                 :            :     }
     872 [ -  + ][ -  + ]:       5343 :     Assert(den != Rational(0));
                 [ -  - ]
     873                 :            : 
     874         [ +  + ]:       5343 :     if (left.isConst())
     875                 :            :     {
     876                 :       2122 :       const Rational& num = left.getConst<Rational>();
     877                 :       4244 :       return RewriteResponse(REWRITE_DONE, nm->mkConstReal(num / den));
     878                 :            :     }
     879         [ -  + ]:       3221 :     if (rewriter::isRAN(left))
     880                 :            :     {
     881                 :            :       return RewriteResponse(REWRITE_DONE,
     882                 :          0 :                              rewriter::ensureReal(nm->mkRealAlgebraicNumber(
     883                 :          0 :                                  rewriter::getRAN(left) / den)));
     884                 :            :     }
     885                 :            : 
     886                 :       3221 :     Node result = nm->mkConstReal(den.inverse());
     887                 :            :     Node mult =
     888                 :       6442 :         rewriter::ensureReal(nodeManager()->mkNode(Kind::MULT, left, result));
     889         [ +  + ]:       3221 :     if (pre)
     890                 :            :     {
     891                 :       3195 :       return RewriteResponse(REWRITE_DONE, mult);
     892                 :            :     }
     893                 :            :     // requires again full since ensureReal may have added a to_real
     894                 :         26 :     return RewriteResponse(REWRITE_AGAIN_FULL, mult);
     895                 :       3221 :   }
     896         [ +  + ]:      10016 :   if (rewriter::isRAN(right))
     897                 :            :   {
     898                 :          4 :     const RealAlgebraicNumber& den = rewriter::getRAN(right);
     899                 :            :     // mkConst is applied to RAN in this block, which are always Real
     900         [ +  + ]:          4 :     if (left.isConst())
     901                 :            :     {
     902                 :            :       return RewriteResponse(
     903                 :            :           REWRITE_DONE,
     904                 :          4 :           rewriter::ensureReal(rewriter::mkConst(
     905                 :          6 :               d_nm, RealAlgebraicNumber(left.getConst<Rational>()) / den)));
     906                 :            :     }
     907         [ +  - ]:          2 :     if (rewriter::isRAN(left))
     908                 :            :     {
     909                 :            :       return RewriteResponse(REWRITE_DONE,
     910                 :          4 :                              rewriter::ensureReal(rewriter::mkConst(
     911                 :          6 :                                  d_nm, rewriter::getRAN(left) / den)));
     912                 :            :     }
     913                 :            : 
     914                 :          0 :     Node result = rewriter::mkConst(d_nm, den.inverse());
     915                 :            :     Node mult =
     916                 :          0 :         rewriter::ensureReal(nodeManager()->mkNode(Kind::MULT, left, result));
     917         [ -  - ]:          0 :     if (pre)
     918                 :            :     {
     919                 :          0 :       return RewriteResponse(REWRITE_DONE, mult);
     920                 :            :     }
     921                 :            :     // requires again full since ensureReal may have added a to_real
     922                 :          0 :     return RewriteResponse(REWRITE_AGAIN_FULL, mult);
     923                 :          0 :   }
     924                 :            :   // We also convert integral rationals in the numerator to integers,
     925                 :            :   // e.g. (/ 1 x) ---> (/ 1.0 x).
     926         [ +  + ]:      10012 :   if (left.getKind() == Kind::CONST_INTEGER)
     927                 :            :   {
     928                 :         43 :     left = nm->mkConstReal(left.getConst<Rational>());
     929                 :            :   }
     930                 :            :   // may have changed due to removing to_real
     931                 :      10012 :   if (left != t[0] || right != t[1])
     932                 :            :   {
     933                 :        290 :     Node ret = nm->mkNode(t.getKind(), left, right);
     934                 :        145 :     return RewriteResponse(REWRITE_AGAIN_FULL, ret);
     935                 :        145 :   }
     936                 :       9867 :   return RewriteResponse(REWRITE_DONE, t);
     937                 :      16544 : }
     938                 :            : 
     939                 :      24357 : RewriteResponse ArithRewriter::rewriteToReal(TNode t)
     940                 :            : {
     941 [ -  + ][ -  + ]:      24357 :   Assert(t.getKind() == Kind::TO_REAL);
                 [ -  - ]
     942         [ +  + ]:      24357 :   if (!t[0].getType().isInteger())
     943                 :            :   {
     944                 :            :     // if it is already real type, then just return the argument
     945                 :          2 :     return RewriteResponse(REWRITE_DONE, t[0]);
     946                 :            :   }
     947                 :      24355 :   NodeManager* nm = nodeManager();
     948         [ +  + ]:      24355 :   if (t[0].isConst())
     949                 :            :   {
     950                 :            :     // If the argument is constant, return a real constant.
     951                 :       4567 :     const Rational& rat = t[0].getConst<Rational>();
     952                 :       9134 :     return RewriteResponse(REWRITE_DONE, nm->mkConstReal(rat));
     953                 :            :   }
     954         [ -  + ]:      19788 :   if (t[0].getKind() == Kind::TO_REAL)
     955                 :            :   {
     956                 :            :     // (to_real (to_real t)) ---> (to_real t)
     957                 :          0 :     return RewriteResponse(REWRITE_DONE, t[0]);
     958                 :            :   }
     959                 :      19788 :   return RewriteResponse(REWRITE_DONE, t);
     960                 :            : }
     961                 :            : 
     962                 :      13559 : RewriteResponse ArithRewriter::rewriteAbs(TNode t)
     963                 :            : {
     964 [ -  + ][ -  + ]:      13559 :   Assert(t.getKind() == Kind::ABS);
                 [ -  - ]
     965 [ -  + ][ -  + ]:      13559 :   Assert(t.getNumChildren() == 1);
                 [ -  - ]
     966                 :            : 
     967         [ +  + ]:      13559 :   if (t[0].isConst())
     968                 :            :   {
     969                 :        347 :     const Rational& rat = t[0].getConst<Rational>();
     970         [ +  + ]:        347 :     if (rat >= 0)
     971                 :            :     {
     972                 :        342 :       return RewriteResponse(REWRITE_DONE, t[0]);
     973                 :            :     }
     974                 :            :     return RewriteResponse(
     975                 :          5 :         REWRITE_DONE, nodeManager()->mkConstRealOrInt(t[0].getType(), -rat));
     976                 :            :   }
     977         [ +  + ]:      13212 :   if (rewriter::isRAN(t[0]))
     978                 :            :   {
     979                 :          2 :     const RealAlgebraicNumber& ran = rewriter::getRAN(t[0]);
     980         [ +  + ]:          2 :     if (ran >= RealAlgebraicNumber())
     981                 :            :     {
     982                 :          1 :       return RewriteResponse(REWRITE_DONE, t[0]);
     983                 :            :     }
     984                 :            :     return RewriteResponse(REWRITE_DONE,
     985                 :          2 :                            nodeManager()->mkRealAlgebraicNumber(-ran));
     986                 :            :   }
     987                 :      13210 :   return RewriteResponse(REWRITE_DONE, t);
     988                 :            : }
     989                 :            : 
     990                 :      15361 : RewriteResponse ArithRewriter::rewriteIntsDivMod(TNode t)
     991                 :            : {
     992                 :      15361 :   NodeManager* nm = nodeManager();
     993                 :      15361 :   Kind k = t.getKind();
     994         [ +  + ]:      15361 :   if (k == Kind::INTS_MODULUS)
     995                 :            :   {
     996                 :      11553 :     if (t[1].isConst() && !t[1].getConst<Rational>().isZero())
     997                 :            :     {
     998                 :            :       // can immediately replace by INTS_MODULUS_TOTAL
     999                 :       4898 :       Node ret = nm->mkNode(Kind::INTS_MODULUS_TOTAL, t[0], t[1]);
    1000                 :       2449 :       return returnRewrite(t, ret, Rewrite::MOD_TOTAL_BY_CONST);
    1001                 :       2449 :     }
    1002                 :            :   }
    1003         [ +  + ]:      12912 :   if (k == Kind::INTS_DIVISION)
    1004                 :            :   {
    1005                 :       3808 :     if (t[1].isConst() && !t[1].getConst<Rational>().isZero())
    1006                 :            :     {
    1007                 :            :       // can immediately replace by INTS_DIVISION_TOTAL
    1008                 :        846 :       Node ret = nm->mkNode(Kind::INTS_DIVISION_TOTAL, t[0], t[1]);
    1009                 :        423 :       return returnRewrite(t, ret, Rewrite::DIV_TOTAL_BY_CONST);
    1010                 :        423 :     }
    1011                 :            :   }
    1012                 :      12489 :   return RewriteResponse(REWRITE_DONE, t);
    1013                 :            : }
    1014                 :            : 
    1015                 :      51740 : RewriteResponse ArithRewriter::rewriteIntsDivModTotal(TNode t, bool pre)
    1016                 :            : {
    1017         [ +  + ]:      51740 :   if (pre)
    1018                 :            :   {
    1019                 :            :     // do not rewrite at prewrite.
    1020                 :      28504 :     return RewriteResponse(REWRITE_DONE, t);
    1021                 :            :   }
    1022                 :      23236 :   NodeManager* nm = nodeManager();
    1023                 :      23236 :   Kind k = t.getKind();
    1024 [ +  + ][ +  - ]:      23236 :   Assert(k == Kind::INTS_MODULUS_TOTAL || k == Kind::INTS_DIVISION_TOTAL);
         [ -  + ][ -  + ]
                 [ -  - ]
    1025                 :      23236 :   TNode n = t[0];
    1026                 :      23236 :   TNode d = t[1];
    1027                 :      23236 :   bool dIsConstant = d.isConst();
    1028 [ +  + ][ +  + ]:      23236 :   if (dIsConstant && d.getConst<Rational>().isZero())
                 [ +  + ]
    1029                 :            :   {
    1030                 :            :     // (div_total x 0) ---> 0 or (mod_total x 0) ---> x
    1031                 :        333 :     Node ret = k == Kind::INTS_MODULUS_TOTAL ? Node(t[0]) : nm->mkConstInt(0);
    1032                 :        206 :     return returnRewrite(t, ret, Rewrite::DIV_MOD_BY_ZERO);
    1033                 :        206 :   }
    1034 [ +  + ][ +  + ]:      23030 :   else if (dIsConstant && d.getConst<Rational>().isOne())
                 [ +  + ]
    1035                 :            :   {
    1036         [ +  + ]:        583 :     if (k == Kind::INTS_MODULUS_TOTAL)
    1037                 :            :     {
    1038                 :            :       // (mod_total x 1) --> 0
    1039                 :         98 :       return returnRewrite(t, nm->mkConstInt(0), Rewrite::MOD_BY_ONE);
    1040                 :            :     }
    1041 [ -  + ][ -  + ]:        485 :     Assert(k == Kind::INTS_DIVISION_TOTAL);
                 [ -  - ]
    1042                 :            :     // (div_total x 1) --> x
    1043                 :        485 :     return returnRewrite(t, n, Rewrite::DIV_BY_ONE);
    1044                 :            :   }
    1045 [ +  + ][ +  + ]:      22447 :   else if (dIsConstant && d.getConst<Rational>().sgn() < 0)
                 [ +  + ]
    1046                 :            :   {
    1047                 :            :     // pull negation
    1048                 :            :     // (div_total x (- c)) ---> (- (div_total x c))
    1049                 :            :     // (mod_total x (- c)) ---> (mod_total x c)
    1050                 :        428 :     Node nn = nm->mkNode(k, t[0], nm->mkConstInt(-t[1].getConst<Rational>()));
    1051 [ +  + ][ +  + ]:        214 :     Node ret = k == Kind::INTS_DIVISION_TOTAL ? nm->mkNode(Kind::NEG, nn) : nn;
                 [ -  - ]
    1052                 :        214 :     return returnRewrite(t, ret, Rewrite::DIV_MOD_PULL_NEG_DEN);
    1053                 :        214 :   }
    1054 [ +  + ][ +  + ]:      22233 :   else if (dIsConstant && n.isConst())
                 [ +  + ]
    1055                 :            :   {
    1056 [ -  + ][ -  + ]:       3598 :     Assert(d.getConst<Rational>().isIntegral());
                 [ -  - ]
    1057 [ -  + ][ -  + ]:       3598 :     Assert(n.getConst<Rational>().isIntegral());
                 [ -  - ]
    1058 [ -  + ][ -  + ]:       3598 :     Assert(!d.getConst<Rational>().isZero());
                 [ -  - ]
    1059                 :       3598 :     Integer di = d.getConst<Rational>().getNumerator();
    1060                 :       3598 :     Integer ni = n.getConst<Rational>().getNumerator();
    1061                 :            : 
    1062                 :       3598 :     bool isDiv = (k == Kind::INTS_DIVISION_TOTAL);
    1063                 :            : 
    1064                 :            :     Integer result = isDiv ? ni.euclidianDivideQuotient(di)
    1065         [ +  + ]:       3598 :                            : ni.euclidianDivideRemainder(di);
    1066                 :            : 
    1067                 :            :     // constant evaluation
    1068                 :            :     // (mod_total c1 c2) ---> c3 or (div_total c1 c2) ---> c3
    1069                 :       3598 :     Node resultNode = nm->mkConstInt(Rational(result));
    1070                 :       3598 :     return returnRewrite(t, resultNode, Rewrite::CONST_EVAL);
    1071                 :       3598 :   }
    1072         [ +  + ]:      18635 :   if (k == Kind::INTS_MODULUS_TOTAL)
    1073                 :            :   {
    1074                 :            :     // Note these rewrites do not need to account for modulus by zero as being
    1075                 :            :     // a UF, which is handled by the reduction of INTS_MODULUS.
    1076                 :      10909 :     Kind k0 = t[0].getKind();
    1077                 :      10909 :     if (k0 == Kind::INTS_MODULUS_TOTAL && t[0][1] == t[1])
    1078                 :            :     {
    1079                 :            :       // (mod_total (mod_total x c) c) --> (mod x c)
    1080                 :         41 :       return returnRewrite(t, t[0], Rewrite::MOD_OVER_MOD);
    1081                 :            :     }
    1082 [ +  + ][ +  + ]:      10868 :     else if (k0 == Kind::NONLINEAR_MULT || k0 == Kind::MULT || k0 == Kind::ADD)
                 [ +  + ]
    1083                 :            :     {
    1084                 :            :       // can drop all
    1085                 :       4230 :       std::vector<Node> newChildren;
    1086                 :       4230 :       bool childChanged = false;
    1087         [ +  + ]:      14526 :       for (const Node& tc : t[0])
    1088                 :            :       {
    1089                 :      10296 :         if (tc.getKind() == Kind::INTS_MODULUS_TOTAL && tc[1] == t[1])
    1090                 :            :         {
    1091                 :        100 :           newChildren.push_back(tc[0]);
    1092                 :        100 :           childChanged = true;
    1093                 :        100 :           continue;
    1094                 :            :         }
    1095                 :      10196 :         newChildren.push_back(tc);
    1096         [ +  + ]:      14526 :       }
    1097         [ +  + ]:       4230 :       if (childChanged)
    1098                 :            :       {
    1099                 :            :         // (mod_total (op ... (mod_total x c) ...) c) --->
    1100                 :            :         // (mod_total (op ... x ...) c) where
    1101                 :            :         // op is one of { NONLINEAR_MULT, MULT, ADD }.
    1102                 :        100 :         Node ret = nm->mkNode(k0, newChildren);
    1103                 :        100 :         ret = nm->mkNode(Kind::INTS_MODULUS_TOTAL, ret, t[1]);
    1104                 :        100 :         return returnRewrite(t, ret, Rewrite::MOD_CHILD_MOD);
    1105                 :        100 :       }
    1106         [ +  + ]:       4230 :     }
    1107                 :            :   }
    1108                 :            :   else
    1109                 :            :   {
    1110 [ -  + ][ -  + ]:       7726 :     Assert(k == Kind::INTS_DIVISION_TOTAL);
                 [ -  - ]
    1111                 :            :     // Note these rewrites do not need to account for division by zero as being
    1112                 :            :     // a UF, which is handled by the reduction of INTS_DIVISION.
    1113                 :       7726 :     if (t[0].getKind() == Kind::INTS_MODULUS_TOTAL && t[0][1] == t[1])
    1114                 :            :     {
    1115                 :            :       // (div_total (mod_total x c) c) --> 0
    1116                 :          0 :       Node ret = nm->mkConstInt(0);
    1117                 :          0 :       return returnRewrite(t, ret, Rewrite::DIV_OVER_MOD);
    1118                 :          0 :     }
    1119                 :            :   }
    1120                 :      18494 :   return RewriteResponse(REWRITE_DONE, t);
    1121                 :      23236 : }
    1122                 :            : 
    1123                 :       5228 : RewriteResponse ArithRewriter::rewriteExtIntegerOp(TNode t)
    1124                 :            : {
    1125 [ +  + ][ +  - ]:       5228 :   Assert(t.getKind() == Kind::TO_INTEGER || t.getKind() == Kind::IS_INTEGER);
         [ -  + ][ -  + ]
                 [ -  - ]
    1126                 :       5228 :   bool isPred = t.getKind() == Kind::IS_INTEGER;
    1127                 :       5228 :   NodeManager* nm = nodeManager();
    1128         [ +  + ]:       5228 :   if (t[0].isConst())
    1129                 :            :   {
    1130                 :        589 :     Node ret;
    1131         [ +  + ]:        589 :     if (isPred)
    1132                 :            :     {
    1133                 :         20 :       ret = nm->mkConst(t[0].getConst<Rational>().isIntegral());
    1134                 :            :     }
    1135                 :            :     else
    1136                 :            :     {
    1137                 :        569 :       ret = nm->mkConstInt(Rational(t[0].getConst<Rational>().floor()));
    1138                 :            :     }
    1139                 :        589 :     return returnRewrite(t, ret, Rewrite::INT_EXT_CONST);
    1140                 :        589 :   }
    1141         [ +  + ]:       4639 :   if (t[0].getType().isInteger())
    1142                 :            :   {
    1143 [ -  + ][ +  - ]:        216 :     Node ret = isPred ? nm->mkConst(true) : Node(t[0]);
                 [ -  - ]
    1144                 :        108 :     return returnRewrite(t, ret, Rewrite::INT_EXT_INT);
    1145                 :        108 :   }
    1146         [ +  + ]:       4531 :   if (t[0].getKind() == Kind::TO_REAL)
    1147                 :            :   {
    1148                 :        228 :     Node ret = nm->mkNode(t.getKind(), t[0][0]);
    1149                 :        114 :     return returnRewrite(t, ret, Rewrite::INT_EXT_TO_REAL);
    1150                 :        114 :   }
    1151         [ +  - ]:       4417 :   if (d_expertEnabled)
    1152                 :            :   {
    1153         [ +  + ]:       4417 :     if (t[0].getKind() == Kind::PI)
    1154                 :            :     {
    1155 [ +  + ][ +  + ]:         14 :       Node ret = isPred ? nm->mkConst(false) : nm->mkConstInt(Rational(3));
                 [ -  - ]
    1156                 :         12 :       return returnRewrite(t, ret, Rewrite::INT_EXT_PI);
    1157                 :         12 :     }
    1158                 :            :   }
    1159                 :       4405 :   return RewriteResponse(REWRITE_DONE, t);
    1160                 :            : }
    1161                 :            : 
    1162                 :       1750 : RewriteResponse ArithRewriter::postRewriteIAnd(TNode t)
    1163                 :            : {
    1164 [ -  + ][ -  + ]:       1750 :   Assert(t.getKind() == Kind::IAND);
                 [ -  - ]
    1165                 :       1750 :   uint32_t bsize = t.getOperator().getConst<IntAnd>().d_size;
    1166                 :       1750 :   NodeManager* nm = nodeManager();
    1167                 :            :   // if constant, we eliminate
    1168                 :       1750 :   if (t[0].isConst() && t[1].isConst())
    1169                 :            :   {
    1170                 :        550 :     Node iToBvop = nm->mkConst(IntToBitVector(bsize));
    1171                 :       1100 :     Node arg1 = nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, t[0]);
    1172                 :       1100 :     Node arg2 = nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, t[1]);
    1173                 :       1100 :     Node bvand = nm->mkNode(Kind::BITVECTOR_AND, arg1, arg2);
    1174                 :        550 :     Node ret = nm->mkNode(Kind::BITVECTOR_UBV_TO_INT, bvand);
    1175                 :        550 :     return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1176                 :        550 :   }
    1177         [ +  + ]:       1200 :   else if (t[0] > t[1])
    1178                 :            :   {
    1179                 :            :     // ((_ iand k) x y) ---> ((_ iand k) y x) if x > y by node ordering
    1180                 :        218 :     Node ret = nm->mkNode(Kind::IAND, t.getOperator(), t[1], t[0]);
    1181                 :        109 :     return RewriteResponse(REWRITE_AGAIN, ret);
    1182                 :        109 :   }
    1183         [ +  + ]:       1091 :   else if (t[0] == t[1])
    1184                 :            :   {
    1185                 :            :     // ((_ iand k) x x) ---> (mod x 2^k)
    1186                 :         64 :     Node twok = nm->mkConstInt(Rational(Integer(2).pow(bsize)));
    1187                 :         64 :     Node ret = nm->mkNode(Kind::INTS_MODULUS, t[0], twok);
    1188                 :         32 :     return RewriteResponse(REWRITE_AGAIN, ret);
    1189                 :         32 :   }
    1190                 :            :   // simplifications involving constants
    1191         [ +  + ]:       3150 :   for (unsigned i = 0; i < 2; i++)
    1192                 :            :   {
    1193         [ +  + ]:       2117 :     if (!t[i].isConst())
    1194                 :            :     {
    1195                 :       1882 :       continue;
    1196                 :            :     }
    1197         [ +  + ]:        235 :     if (t[i].getConst<Rational>().sgn() == 0)
    1198                 :            :     {
    1199                 :            :       // ((_ iand k) 0 y) ---> 0
    1200                 :          1 :       return RewriteResponse(REWRITE_DONE, t[i]);
    1201                 :            :     }
    1202         [ +  + ]:        234 :     if (t[i].getConst<Rational>().getNumerator() == Integer(2).pow(bsize) - 1)
    1203                 :            :     {
    1204                 :            :       // ((_ iand k) 111...1 y) ---> (mod y 2^k)
    1205                 :         50 :       Node twok = nm->mkConstInt(Rational(Integer(2).pow(bsize)));
    1206                 :         50 :       Node ret = nm->mkNode(Kind::INTS_MODULUS, t[1 - i], twok);
    1207                 :         25 :       return RewriteResponse(REWRITE_AGAIN, ret);
    1208                 :         25 :     }
    1209                 :            :   }
    1210                 :       1033 :   return RewriteResponse(REWRITE_DONE, t);
    1211                 :            : }
    1212                 :            : 
    1213                 :        775 : RewriteResponse ArithRewriter::postRewritePIAnd(TNode t)
    1214                 :            : {
    1215 [ -  + ][ -  + ]:        775 :   Assert(t.getKind() == Kind::PIAND);
                 [ -  - ]
    1216                 :        775 :   NodeManager* nm = nodeManager();
    1217                 :            :   // simplifications involving constants
    1218 [ +  + ][ -  - ]:        775 :   if (t[0].isConst()
    1219 [ +  + ][ +  + ]:       1570 :       && (t[0].getConst<Rational>().sgn() == 0
         [ +  - ][ -  - ]
    1220 [ +  + ][ +  + ]:        795 :           || t[0].getConst<Rational>().sgn() == -1))
         [ +  + ][ -  - ]
    1221                 :            :   {
    1222                 :         80 :     return RewriteResponse(REWRITE_DONE, nm->mkConstInt(Rational(0)));
    1223                 :            :   }
    1224         [ +  + ]:       2161 :   for (unsigned i = 1; i < 3; i++)
    1225                 :            :   {
    1226         [ +  + ]:       1454 :     if (!t[i].isConst())
    1227                 :            :     {
    1228                 :       1426 :       continue;
    1229                 :            :     }
    1230         [ +  + ]:        108 :     if (t[i].getConst<Rational>().sgn() == 0)
    1231                 :            :     {
    1232                 :            :       // (piand k 0 y) ---> 0
    1233                 :         44 :       return RewriteResponse(REWRITE_DONE, nm->mkConstInt(Rational(0)));
    1234                 :            :     }
    1235         [ +  + ]:         86 :     if (!t[0].isConst())
    1236                 :            :     {
    1237                 :         80 :       continue;
    1238                 :            :     }
    1239                 :          6 :     size_t bsize = t[0].getConst<Rational>().getNumerator().toUnsignedInt();
    1240                 :          6 :     Node twok = nm->mkNode(Kind::POW2, t[0]);
    1241                 :         12 :     Node maxsign = nm->mkConstInt(Rational(Integer(2).pow(bsize) - 1));
    1242                 :         12 :     if (t[i].getConst<Rational>().getNumerator()
    1243         [ +  - ]:         18 :         == maxsign.getConst<Rational>().getNumerator())
    1244                 :            :     {
    1245                 :            :       // (piand k 111...1 y) ---> (mod y 2^k)
    1246         [ +  - ]:          6 :       if (i == 1)
    1247                 :            :       {
    1248                 :         12 :         Node ret = nm->mkNode(Kind::INTS_MODULUS, t[2], twok);
    1249                 :          6 :         return RewriteResponse(REWRITE_AGAIN, ret);
    1250                 :          6 :       }
    1251         [ -  - ]:          0 :       else if (i == 2)
    1252                 :            :       {
    1253                 :          0 :         Node ret = nm->mkNode(Kind::INTS_MODULUS, t[1], twok);
    1254                 :          0 :         return RewriteResponse(REWRITE_AGAIN, ret);
    1255                 :          0 :       }
    1256                 :            :     }
    1257 [ -  + ][ -  + ]:         12 :   }
    1258                 :            :   // if constant, we eliminate
    1259                 :        707 :   if (t[0].isConst() && t[1].isConst() && t[2].isConst())
    1260                 :            :   {
    1261                 :          0 :     size_t bsize = t[0].getConst<Rational>().getNumerator().toUnsignedInt();
    1262                 :          0 :     Node iToBvop = nm->mkConst(IntToBitVector(bsize));
    1263                 :          0 :     Node arg1 = nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, t[1]);
    1264                 :          0 :     Node arg2 = nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, t[2]);
    1265                 :          0 :     Node bvand = nm->mkNode(Kind::BITVECTOR_AND, arg1, arg2);
    1266                 :          0 :     Node ret = nm->mkNode(Kind::BITVECTOR_UBV_TO_INT, bvand);
    1267                 :          0 :     return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1268                 :          0 :   }
    1269         [ +  + ]:        707 :   else if (t[1] > t[2])
    1270                 :            :   {
    1271                 :            :     // (piand k x y) ---> (piand k y x) if x > y by node ordering
    1272                 :        184 :     Node ret = nm->mkNode(Kind::PIAND, t[0], t[2], t[1]);
    1273                 :         92 :     return RewriteResponse(REWRITE_AGAIN, ret);
    1274                 :         92 :   }
    1275         [ +  + ]:        615 :   else if (t[1] == t[2])
    1276                 :            :   {
    1277                 :            :     // (piand k x x) ---> (mod x 2^k)
    1278                 :         20 :     Node twok = nm->mkNode(Kind::POW2, t[0]);
    1279                 :         40 :     Node ret = nm->mkNode(Kind::INTS_MODULUS, t[1], twok);
    1280                 :         20 :     return RewriteResponse(REWRITE_AGAIN, ret);
    1281                 :         20 :   }
    1282                 :        595 :   return RewriteResponse(REWRITE_DONE, t);
    1283                 :            : }
    1284                 :            : 
    1285                 :       1982 : RewriteResponse ArithRewriter::postRewritePow2(TNode t)
    1286                 :            : {
    1287 [ -  + ][ -  + ]:       1982 :   Assert(t.getKind() == Kind::POW2);
                 [ -  - ]
    1288                 :            :   // if constant, we eliminate
    1289         [ +  + ]:       1982 :   if (t[0].isConst())
    1290                 :            :   {
    1291                 :            :     // pow2 is only supported for integers
    1292         [ +  - ]:       1924 :     Trace("arith-rewriter")
    1293                 :        962 :         << "ArithRewriter::postRewritePow2, t:" << t << std::endl;
    1294 [ -  + ][ -  + ]:        962 :     Assert(t[0].getType().isInteger());
                 [ -  - ]
    1295                 :            :     // use the evaluator definition for rewriting this
    1296                 :        962 :     Evaluator eval(nullptr);
    1297                 :       1924 :     Node ret = eval.eval(t, {}, {});
    1298         [ +  + ]:        962 :     if (!ret.isNull())
    1299                 :            :     {
    1300                 :        946 :       return RewriteResponse(REWRITE_DONE, ret);
    1301                 :            :     }
    1302         [ +  + ]:        962 :   }
    1303                 :       1036 :   return RewriteResponse(REWRITE_DONE, t);
    1304                 :            : }
    1305                 :            : 
    1306                 :        136 : RewriteResponse ArithRewriter::postRewriteIntsIsPow2(TNode t)
    1307                 :            : {
    1308 [ -  + ][ -  + ]:        136 :   Assert(t.getKind() == Kind::INTS_ISPOW2);
                 [ -  - ]
    1309                 :            :   // if constant, we eliminate
    1310         [ +  - ]:        136 :   if (t[0].isConst())
    1311                 :            :   {
    1312                 :            :     // pow2 is only supported for integers
    1313 [ -  + ][ -  + ]:        136 :     Assert(t[0].getType().isInteger());
                 [ -  - ]
    1314                 :        136 :     Integer i = t[0].getConst<Rational>().getNumerator();
    1315                 :            : 
    1316                 :        272 :     return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, i.isPow2()));
    1317                 :        136 :   }
    1318                 :          0 :   return RewriteResponse(REWRITE_DONE, t);
    1319                 :            : }
    1320                 :        209 : RewriteResponse ArithRewriter::postRewriteIntsLog2(TNode t)
    1321                 :            : {
    1322 [ -  + ][ -  + ]:        209 :   Assert(t.getKind() == Kind::INTS_LOG2);
                 [ -  - ]
    1323                 :            :   // if constant, we eliminate
    1324         [ +  + ]:        209 :   if (t[0].isConst())
    1325                 :            :   {
    1326                 :            :     // log2 is only supported for integers
    1327 [ -  + ][ -  + ]:        153 :     Assert(t[0].getType().isInteger());
                 [ -  - ]
    1328                 :        153 :     const Rational& r = t[0].getConst<Rational>();
    1329                 :            :     // default to 0 for negative inputs
    1330         [ +  + ]:        153 :     if (r.sgn() < 0)
    1331                 :            :     {
    1332                 :          2 :       return RewriteResponse(REWRITE_DONE, rewriter::mkConst(d_nm, Integer(0)));
    1333                 :            :     }
    1334                 :            :     // for non-negative inputs, this
    1335                 :            :     // is captured by `length()` of `Integer`.
    1336                 :        152 :     Integer i = r.getNumerator();
    1337                 :        152 :     size_t const length = i.length();
    1338                 :            :     return RewriteResponse(REWRITE_DONE,
    1339                 :        304 :                            rewriter::mkConst(d_nm, Integer(length - 1)));
    1340                 :        152 :   }
    1341                 :         56 :   return RewriteResponse(REWRITE_DONE, t);
    1342                 :            : }
    1343                 :            : 
    1344                 :       7960 : RewriteResponse ArithRewriter::postRewriteTranscendental(TNode t)
    1345                 :            : {
    1346         [ +  - ]:      15920 :   Trace("arith-tf-rewrite")
    1347                 :       7960 :       << "Rewrite transcendental function : " << t << std::endl;
    1348 [ -  + ][ -  + ]:       7960 :   Assert(t.getTypeOrNull(true).isReal());
                 [ -  - ]
    1349                 :       7960 :   NodeManager* nm = nodeManager();
    1350 [ +  + ][ +  + ]:       7960 :   switch (t.getKind())
         [ +  + ][ +  + ]
    1351                 :            :   {
    1352                 :       1404 :     case Kind::EXPONENTIAL:
    1353                 :            :     {
    1354         [ +  + ]:       1404 :       if (t[0].isConst())
    1355                 :            :       {
    1356                 :        772 :         Rational r = t[0].getConst<Rational>();
    1357         [ +  + ]:        772 :         if (r.sgn() == 0)
    1358                 :            :         {
    1359                 :         54 :           Node one = nm->mkConstReal(Rational(1));
    1360                 :            :           // (= (exp 0.0) 1.0)
    1361                 :         54 :           return RewriteResponse(REWRITE_DONE, one);
    1362                 :         54 :         }
    1363                 :            :         else
    1364                 :            :         {
    1365                 :        718 :           return RewriteResponse(REWRITE_DONE, t);
    1366                 :            :         }
    1367                 :        772 :       }
    1368         [ +  + ]:        632 :       else if (t[0].getKind() == Kind::ADD)
    1369                 :            :       {
    1370                 :         65 :         std::vector<Node> product;
    1371         [ +  + ]:        195 :         for (const Node tc : t[0])
    1372                 :            :         {
    1373                 :        130 :           Node tcr = rewriter::ensureReal(tc);
    1374                 :        130 :           product.push_back(nm->mkNode(Kind::EXPONENTIAL, tcr));
    1375                 :        195 :         }
    1376                 :            :         // We need to do a full rewrite here, since we can get exponentials of
    1377                 :            :         // constants, e.g. when we are rewriting exp(2 + x)
    1378                 :            :         return RewriteResponse(REWRITE_AGAIN_FULL,
    1379                 :        130 :                                nm->mkNode(Kind::MULT, product));
    1380                 :         65 :       }
    1381                 :            :     }
    1382                 :        567 :     break;
    1383                 :       5764 :     case Kind::SINE:
    1384         [ +  + ]:       5764 :       if (t[0].isConst())
    1385                 :            :       {
    1386                 :       2177 :         const Rational& rat = t[0].getConst<Rational>();
    1387         [ +  + ]:       2177 :         if (rat.sgn() == 0)
    1388                 :            :         {
    1389                 :        110 :           return RewriteResponse(REWRITE_DONE, nm->mkConstReal(Rational(0)));
    1390                 :            :         }
    1391         [ +  + ]:       2122 :         else if (rat.sgn() == -1)
    1392                 :            :         {
    1393                 :            :           Node ret = nm->mkNode(Kind::NEG,
    1394                 :        330 :                                 nm->mkNode(Kind::SINE, nm->mkConstReal(-rat)));
    1395                 :        165 :           return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1396                 :        165 :         }
    1397                 :            :       }
    1398 [ +  + ][ -  - ]:       3587 :       else if ((t[0].getKind() == Kind::MULT
    1399 [ -  + ][ +  - ]:       7078 :                 || t[0].getKind() == Kind::NONLINEAR_MULT)
                 [ -  - ]
    1400                 :       7078 :                && t[0][0].isConst() && t[0][0].getConst<Rational>().sgn() == -1)
    1401                 :            :       {
    1402                 :            :         // sin(-n*x) ---> -sin(n*x)
    1403                 :         30 :         std::vector<Node> mchildren(t[0].begin(), t[0].end());
    1404                 :         15 :         mchildren[0] = nm->mkConstReal(-t[0][0].getConst<Rational>());
    1405                 :            :         Node ret = nm->mkNode(
    1406                 :            :             Kind::NEG,
    1407                 :         30 :             nm->mkNode(Kind::SINE, nm->mkNode(t[0].getKind(), mchildren)));
    1408                 :         15 :         return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1409                 :         15 :       }
    1410                 :            :       else
    1411                 :            :       {
    1412                 :            :         // get the factor of PI in the argument
    1413                 :       3572 :         Node pi_factor;
    1414                 :       3572 :         Node pi;
    1415                 :       3572 :         Node rem;
    1416                 :       3572 :         std::map<Node, Node> msum;
    1417         [ +  - ]:       3572 :         if (ArithMSum::getMonomialSum(t[0], msum))
    1418                 :            :         {
    1419                 :       3572 :           pi = mkPi(nm);
    1420                 :       3572 :           std::map<Node, Node>::iterator itm = msum.find(pi);
    1421         [ +  + ]:       3572 :           if (itm != msum.end())
    1422                 :            :           {
    1423         [ +  + ]:       2116 :             if (itm->second.isNull())
    1424                 :            :             {
    1425                 :         12 :               pi_factor = rewriter::mkConst(d_nm, Integer(1));
    1426                 :            :             }
    1427                 :            :             else
    1428                 :            :             {
    1429                 :       2104 :               pi_factor = itm->second;
    1430                 :            :             }
    1431                 :       2116 :             msum.erase(pi);
    1432         [ +  + ]:       2116 :             if (!msum.empty())
    1433                 :            :             {
    1434                 :       2033 :               rem = ArithMSum::mkNode(nm, msum);
    1435                 :            :             }
    1436                 :            :           }
    1437                 :            :         }
    1438                 :            :         else
    1439                 :            :         {
    1440                 :          0 :           DebugUnhandled();
    1441                 :            :         }
    1442                 :            : 
    1443                 :            :         // if there is a factor of PI
    1444         [ +  + ]:       3572 :         if (!pi_factor.isNull())
    1445                 :            :         {
    1446         [ +  - ]:       4232 :           Trace("arith-tf-rewrite-debug")
    1447                 :       2116 :               << "Process pi factor = " << pi_factor << std::endl;
    1448                 :       2116 :           Rational r = pi_factor.getConst<Rational>();
    1449                 :       2116 :           Rational r_abs = r.abs();
    1450                 :       2116 :           Rational rone = Rational(1);
    1451                 :       2116 :           Rational rtwo = Rational(2);
    1452         [ +  + ]:       2116 :           if (r_abs > rone)
    1453                 :            :           {
    1454                 :            :             // add/substract 2*pi beyond scope
    1455                 :          1 :             Rational ra_div_two = (r_abs + rone) / rtwo;
    1456                 :          1 :             Node new_pi_factor;
    1457         [ +  - ]:          1 :             if (r.sgn() == 1)
    1458                 :            :             {
    1459                 :          1 :               new_pi_factor = nm->mkConstReal(r - rtwo * ra_div_two.floor());
    1460                 :            :             }
    1461                 :            :             else
    1462                 :            :             {
    1463                 :          0 :               Assert(r.sgn() == -1);
    1464                 :          0 :               new_pi_factor = nm->mkConstReal(r + rtwo * ra_div_two.floor());
    1465                 :            :             }
    1466                 :          2 :             Node new_arg = nm->mkNode(Kind::MULT, new_pi_factor, pi);
    1467         [ +  - ]:          1 :             if (!rem.isNull())
    1468                 :            :             {
    1469                 :          1 :               new_arg = nm->mkNode(Kind::ADD, new_arg, rem);
    1470                 :            :             }
    1471                 :          1 :             new_arg = rewriter::ensureReal(new_arg);
    1472                 :            :             // sin( 2*n*PI + x ) = sin( x )
    1473                 :            :             return RewriteResponse(REWRITE_AGAIN_FULL,
    1474                 :          2 :                                    nm->mkNode(Kind::SINE, new_arg));
    1475                 :          1 :           }
    1476         [ +  + ]:       2115 :           else if (r_abs == rone)
    1477                 :            :           {
    1478                 :            :             // sin( PI + x ) = -sin( x )
    1479         [ +  + ]:         12 :             if (rem.isNull())
    1480                 :            :             {
    1481                 :            :               return RewriteResponse(REWRITE_DONE,
    1482                 :          4 :                                      nm->mkConstReal(Rational(0)));
    1483                 :            :             }
    1484                 :            :             else
    1485                 :            :             {
    1486                 :         10 :               rem = rewriter::ensureReal(rem);
    1487                 :            :               return RewriteResponse(
    1488                 :            :                   REWRITE_AGAIN_FULL,
    1489                 :         20 :                   nm->mkNode(Kind::NEG, nm->mkNode(Kind::SINE, rem)));
    1490                 :            :             }
    1491                 :            :           }
    1492         [ +  + ]:       2103 :           else if (rem.isNull())
    1493                 :            :           {
    1494                 :            :             // other rational cases based on Niven's theorem
    1495                 :            :             // (https://en.wikipedia.org/wiki/Niven%27s_theorem)
    1496                 :         81 :             Integer one = Integer(1);
    1497                 :         81 :             Integer two = Integer(2);
    1498                 :         81 :             Integer six = Integer(6);
    1499         [ +  - ]:         81 :             if (r_abs.getDenominator() == two)
    1500                 :            :             {
    1501 [ -  + ][ -  + ]:         81 :               Assert(r_abs.getNumerator() == one);
                 [ -  - ]
    1502                 :            :               return RewriteResponse(REWRITE_DONE,
    1503                 :        162 :                                      nm->mkConstReal(Rational(r.sgn())));
    1504                 :            :             }
    1505         [ -  - ]:          0 :             else if (r_abs.getDenominator() == six)
    1506                 :            :             {
    1507                 :          0 :               Integer five = Integer(5);
    1508                 :          0 :               if (r_abs.getNumerator() == one || r_abs.getNumerator() == five)
    1509                 :            :               {
    1510                 :            :                 return RewriteResponse(
    1511                 :            :                     REWRITE_DONE,
    1512                 :          0 :                     nm->mkConstReal(Rational(r.sgn()) / Rational(2)));
    1513                 :            :               }
    1514         [ -  - ]:          0 :             }
    1515 [ -  + ][ -  + ]:        243 :           }
                 [ -  + ]
    1516 [ +  + ][ +  + ]:       2398 :         }
         [ +  + ][ +  + ]
    1517 [ +  + ][ +  + ]:       3854 :       }
         [ +  + ][ +  + ]
    1518                 :       5435 :       break;
    1519                 :        268 :     case Kind::COSINE:
    1520                 :            :     {
    1521                 :            :       return RewriteResponse(
    1522                 :            :           REWRITE_AGAIN_FULL,
    1523                 :        536 :           nm->mkNode(
    1524                 :            :               Kind::SINE,
    1525                 :       1072 :               nm->mkNode(Kind::SUB,
    1526 [ +  + ][ -  - ]:       1340 :                          nm->mkNode(Kind::MULT,
    1527                 :        536 :                                     {nm->mkConstReal(Rational(1) / Rational(2)),
    1528                 :        536 :                                      mkPi(nm)}),
    1529                 :        268 :                          t[0])));
    1530                 :            :     }
    1531                 :            :     break;
    1532                 :         57 :     case Kind::TANGENT:
    1533                 :            :     {
    1534                 :            :       return RewriteResponse(REWRITE_AGAIN_FULL,
    1535 [ +  + ][ -  - ]:        285 :                              nm->mkNode(Kind::DIVISION,
    1536                 :        114 :                                         {nm->mkNode(Kind::SINE, t[0]),
    1537                 :        171 :                                          nm->mkNode(Kind::COSINE, t[0])}));
    1538                 :            :     }
    1539                 :            :     break;
    1540                 :         20 :     case Kind::COSECANT:
    1541                 :            :     {
    1542                 :            :       return RewriteResponse(REWRITE_AGAIN_FULL,
    1543 [ +  + ][ -  - ]:        100 :                              nm->mkNode(Kind::DIVISION,
    1544                 :         40 :                                         {nm->mkConstReal(Rational(1)),
    1545                 :         60 :                                          nm->mkNode(Kind::SINE, t[0])}));
    1546                 :            :     }
    1547                 :            :     break;
    1548                 :         43 :     case Kind::SECANT:
    1549                 :            :     {
    1550                 :            :       return RewriteResponse(REWRITE_AGAIN_FULL,
    1551 [ +  + ][ -  - ]:        215 :                              nm->mkNode(Kind::DIVISION,
    1552                 :         86 :                                         {nm->mkConstReal(Rational(1)),
    1553                 :        129 :                                          nm->mkNode(Kind::COSINE, t[0])}));
    1554                 :            :     }
    1555                 :            :     break;
    1556                 :         22 :     case Kind::COTANGENT:
    1557                 :            :     {
    1558                 :            :       return RewriteResponse(REWRITE_AGAIN_FULL,
    1559 [ +  + ][ -  - ]:        110 :                              nm->mkNode(Kind::DIVISION,
    1560                 :         44 :                                         {nm->mkNode(Kind::COSINE, t[0]),
    1561                 :         66 :                                          nm->mkNode(Kind::SINE, t[0])}));
    1562                 :            :     }
    1563                 :            :     break;
    1564                 :        382 :     default: break;
    1565                 :            :   }
    1566                 :       6384 :   return RewriteResponse(REWRITE_DONE, t);
    1567                 :            : }
    1568                 :            : 
    1569                 :      46900 : Node ArithRewriter::expandDefinition(Node node)
    1570                 :            : {
    1571                 :            :   // call eliminate operators, to eliminate partial operators only
    1572                 :      46900 :   std::vector<SkolemLemma> lems;
    1573                 :      46900 :   TrustNode ret = d_opElim.eliminate(node, lems, true);
    1574 [ -  + ][ -  + ]:      46900 :   Assert(lems.empty());
                 [ -  - ]
    1575         [ +  + ]:      46900 :   if (ret.isNull())
    1576                 :            :   {
    1577                 :      46696 :     return Node::null();
    1578                 :            :   }
    1579                 :        204 :   return ret.getNode();
    1580                 :      46900 : }
    1581                 :            : 
    1582                 :       8437 : RewriteResponse ArithRewriter::returnRewrite(TNode t, Node ret, Rewrite r)
    1583                 :            : {
    1584         [ +  - ]:      16874 :   Trace("arith-rewriter") << "ArithRewriter : " << t << " == " << ret << " by "
    1585                 :       8437 :                           << r << std::endl;
    1586                 :       8437 :   return RewriteResponse(REWRITE_AGAIN_FULL, ret);
    1587                 :            : }
    1588                 :            : 
    1589                 :     224811 : Node ArithRewriter::rewriteIneqToBv(const Node& ineq)
    1590                 :            : {
    1591 [ -  + ][ -  + ]:     224811 :   Assert(ineq.getKind() == Kind::GEQ);
                 [ -  - ]
    1592                 :            : 
    1593                 :     449622 :   Node left = rewriter::removeToReal(ineq[0]);
    1594                 :     449622 :   Node right = rewriter::removeToReal(ineq[1]);
    1595                 :            : 
    1596                 :     224811 :   rewriter::Sum sum;
    1597                 :     224811 :   rewriter::addToSum(sum, left, false);
    1598                 :     224811 :   rewriter::addToSum(sum, right, true);
    1599                 :            : 
    1600                 :     449622 :   return rewriteIneqToBv(Kind::GEQ, sum, ineq);
    1601                 :     224811 : }
    1602                 :            : 
    1603                 :     224811 : Node ArithRewriter::rewriteIneqToBv(Kind kind,
    1604                 :            :                                     const rewriter::Sum& sum,
    1605                 :            :                                     const Node& ineq)
    1606                 :            : {
    1607                 :     224811 :   bool convertible = true;
    1608                 :            :   // the (single) bv2nat term in the sum
    1609                 :     224811 :   Node bv2natTerm;
    1610                 :            :   // whether the bv2nat term is positive in the sum
    1611                 :     224811 :   bool bv2natPol = false;
    1612                 :            :   // the remaining sum (constant)
    1613                 :     224811 :   std::vector<Node> otherSum;
    1614                 :     224811 :   NodeManager* nm = nodeManager();
    1615         [ +  + ]:     365042 :   for (const std::pair<const Node, RealAlgebraicNumber>& m : sum)
    1616                 :            :   {
    1617         [ +  - ]:     365001 :     if (m.second.isRational())
    1618                 :            :     {
    1619                 :     365001 :       const Rational& r = m.second.toRational();
    1620                 :     365001 :       Kind mk = m.first.getKind();
    1621         [ +  + ]:     365001 :       if (mk == Kind::BITVECTOR_UBV_TO_INT)
    1622                 :            :       {
    1623                 :            :         // We currently only eliminate sums involving exactly one
    1624                 :            :         // (bv2nat x) monomial whose coefficient is +- 1, although more
    1625                 :            :         // cases could be handled here.
    1626         [ +  + ]:         47 :         if (bv2natTerm.isNull())
    1627                 :            :         {
    1628         [ +  + ]:         45 :           if (r.abs().isOne())
    1629                 :            :           {
    1630                 :         43 :             bv2natPol = (r.sgn() == 1);
    1631                 :         43 :             bv2natTerm = m.first;
    1632                 :         43 :             continue;
    1633                 :            :           }
    1634                 :            :         }
    1635                 :            :         else
    1636                 :            :         {
    1637                 :          2 :           convertible = false;
    1638                 :          2 :           break;
    1639                 :            :         }
    1640                 :            :       }
    1641 [ +  + ][ +  - ]:     364954 :       else if (mk == Kind::CONST_INTEGER && m.second.isRational())
                 [ +  + ]
    1642                 :            :       {
    1643         [ +  + ]:     149670 :         if (r.isIntegral())
    1644                 :            :         {
    1645                 :     140188 :           otherSum.push_back(nm->mkConstInt(r));
    1646                 :     140188 :           continue;
    1647                 :            :         }
    1648                 :            :       }
    1649                 :            :       // if a non-constant, non-bv2nat term is in the sum, we fail
    1650    [ +  + ][ + ]:     365001 :     }
    1651                 :     224768 :     convertible = false;
    1652                 :     224768 :     break;
    1653                 :            :   }
    1654 [ +  + ][ +  - ]:     224811 :   if (convertible && !bv2natTerm.isNull())
                 [ +  + ]
    1655                 :            :   {
    1656                 :         41 :     Node zero = nm->mkConstInt(Rational(0));
    1657                 :         41 :     Kind bvKind =
    1658                 :            :         (kind == Kind::GT
    1659 [ -  + ][ -  - ]:         82 :              ? (bv2natPol ? Kind::BITVECTOR_UGT : Kind::BITVECTOR_ULT)
    1660         [ +  - ]:         41 :              : (bv2natPol ? Kind::BITVECTOR_UGE : Kind::BITVECTOR_ULE));
    1661                 :         41 :     Node bvt = bv2natTerm[0];
    1662                 :         41 :     size_t bvsize = bvt.getType().getBitVectorSize();
    1663                 :         82 :     Node w = nm->mkConstInt(Rational(Integer(2).pow(bvsize)));
    1664                 :         41 :     Node osum = otherSum.empty()
    1665                 :            :                     ? zero
    1666                 :         40 :                     : (otherSum.size() == 1 ? otherSum[0]
    1667 [ +  + ][ +  - ]:         81 :                                             : nm->mkNode(Kind::ADD, otherSum));
    1668                 :            :     // possibly negate the sum
    1669                 :            :     Node o = bv2natPol
    1670                 :         41 :                  ? (osum.getKind() == Kind::NEG ? osum[0]
    1671                 :            :                                                 : nm->mkNode(Kind::NEG, osum))
    1672 [ +  - ][ -  + ]:         82 :                  : osum;
         [ +  - ][ -  - ]
    1673                 :         82 :     Node ub = nm->mkNode(Kind::GEQ, o, w);
    1674                 :         82 :     Node lb = nm->mkNode(Kind::LT, o, zero);
    1675                 :         41 :     Node iToBvop = nm->mkConst(IntToBitVector(bvsize));
    1676                 :        164 :     Node ret = nm->mkNode(
    1677                 :            :         Kind::ITE,
    1678                 :            :         {ub,
    1679                 :         41 :          nm->mkConst(!bv2natPol),
    1680                 :        328 :          nm->mkNode(
    1681                 :            :              Kind::ITE,
    1682                 :            :              {lb,
    1683                 :         82 :               nm->mkConst(bv2natPol),
    1684                 :         82 :               nm->mkNode(bvKind,
    1685                 :            :                          bvt,
    1686                 :        246 :                          nm->mkNode(Kind::INT_TO_BITVECTOR, iToBvop, o))})});
    1687                 :            :     // E.g. (<= (bv2nat x) N) -->
    1688                 :            :     //      (ite (>= N 2^w) true (ite (< N 0) false (bvule x ((_ int2bv w) N))
    1689                 :            :     // or   (<= N (bv2nat x)) -->
    1690                 :            :     //      (ite (>= N 2^w) false (ite (< N 0) true (bvuge x ((_ int2bv w) N))
    1691                 :            :     // where N is a constant. Note that ((_ int2bv w) N) will subsequently
    1692                 :            :     // be rewritten to the appropriate bitvector constant.
    1693                 :         41 :     return ret;
    1694                 :         41 :   }
    1695                 :     224770 :   return ineq;
    1696                 :     224811 : }
    1697                 :            : 
    1698                 :        250 : Node ArithRewriter::expandPowConst(NodeManager* nm, const Node& t)
    1699                 :            : {
    1700         [ +  + ]:        250 :   if (t[1].isConst())
    1701                 :            :   {
    1702                 :        242 :     const Rational& exp = t[1].getConst<Rational>();
    1703         [ -  + ]:        242 :     if (!exp.isIntegral())
    1704                 :            :     {
    1705                 :        238 :       return Node::null();
    1706                 :            :     }
    1707                 :        242 :     TNode base = t[0];
    1708         [ +  + ]:        242 :     if (exp.sgn() == 0)
    1709                 :            :     {
    1710                 :         50 :       return nm->mkConstRealOrInt(t.getType(), Rational(1));
    1711                 :            :     }
    1712         [ +  + ]:        217 :     else if (exp.sgn() > 0)
    1713                 :            :     {
    1714                 :        215 :       Rational r(expr::NodeValue::MAX_CHILDREN);
    1715         [ +  + ]:        215 :       if (exp <= r)
    1716                 :            :       {
    1717                 :        213 :         unsigned num = exp.getNumerator().toUnsignedInt();
    1718                 :        213 :         Node ret;
    1719         [ +  + ]:        213 :         if (num == 1)
    1720                 :            :         {
    1721                 :         35 :           ret = base;
    1722                 :            :         }
    1723                 :            :         else
    1724                 :            :         {
    1725                 :        178 :           NodeBuilder nb(nm, Kind::MULT);
    1726         [ +  + ]:        939 :           for (unsigned i = 0; i < num; ++i)
    1727                 :            :           {
    1728                 :        761 :             nb << base;
    1729                 :            :           }
    1730 [ -  + ][ -  + ]:        178 :           Assert(nb.getNumChildren() > 0);
                 [ -  - ]
    1731                 :        178 :           ret = nb;
    1732                 :        178 :         }
    1733                 :        213 :         return ret;
    1734                 :        213 :       }
    1735         [ +  + ]:        215 :     }
    1736         [ +  + ]:        242 :   }
    1737                 :         12 :   return Node::null();
    1738                 :            : }
    1739                 :            : 
    1740                 :            : }  // namespace arith
    1741                 :            : }  // namespace theory
    1742                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14