1 /********************* */
2 /*! \file theory_fp_rewriter.cpp
4 ** Top contributors (to current version):
5 ** Martin Brain, Paul Meng, Tim King
6 ** Copyright (c) 2013 University of Oxford
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2017 by the authors listed in the file AUTHORS
9 ** in the top-level source directory) and their institutional affiliations.
10 ** All rights reserved. See the file COPYING in the top-level source
11 ** directory for licensing information.\endverbatim
13 ** \brief [[ Rewrite rules for floating point theories. ]]
15 ** \todo [[ Constant folding
16 ** Push negations up through arithmetic operators (include max and min? maybe not due to +0/-0)
17 ** classifications to normal tests (maybe)
18 ** (= x (fp.neg x)) --> (isNaN x)
19 ** (fp.eq x (fp.neg x)) --> (isZero x) (previous and reorganise should be sufficient)
20 ** (fp.eq x const) --> various = depending on const
21 ** (fp.abs (fp.neg x)) --> (fp.abs x)
22 ** (fp.isPositive (fp.neg x)) --> (fp.isNegative x)
23 ** (fp.isNegative (fp.neg x)) --> (fp.isPositive x)
24 ** (fp.isPositive (fp.abs x)) --> (not (isNaN x))
25 ** (fp.isNegative (fp.abs x)) --> false
31 #include "base/cvc4_assert.h"
32 #include "theory/fp/theory_fp_rewriter.h"
40 template <RewriteFunction first
, RewriteFunction second
>
41 RewriteResponse
then (TNode node
, bool isPreRewrite
) {
42 RewriteResponse
result(first(node
, isPreRewrite
));
44 if (result
.status
== REWRITE_DONE
) {
45 return second(result
.node
, isPreRewrite
);
51 RewriteResponse
notFP (TNode node
, bool) {
52 Unreachable("non floating-point kind (%d) in floating point rewrite?",node
.getKind());
55 RewriteResponse
identity (TNode node
, bool) {
56 return RewriteResponse(REWRITE_DONE
, node
);
59 RewriteResponse
type (TNode node
, bool) {
60 Unreachable("sort kind (%d) found in expression?",node
.getKind());
61 return RewriteResponse(REWRITE_DONE
, node
);
64 RewriteResponse
removeDoubleNegation (TNode node
, bool) {
65 Assert(node
.getKind() == kind::FLOATINGPOINT_NEG
);
66 if (node
[0].getKind() == kind::FLOATINGPOINT_NEG
) {
67 RewriteResponse(REWRITE_AGAIN
, node
[0][0]);
70 return RewriteResponse(REWRITE_DONE
, node
);
73 RewriteResponse
convertSubtractionToAddition (TNode node
, bool) {
74 Assert(node
.getKind() == kind::FLOATINGPOINT_SUB
);
75 Node negation
= NodeManager::currentNM()->mkNode(kind::FLOATINGPOINT_NEG
,node
[2]);
76 Node addition
= NodeManager::currentNM()->mkNode(kind::FLOATINGPOINT_PLUS
,node
[0],node
[1],negation
);
77 return RewriteResponse(REWRITE_DONE
, addition
);
80 RewriteResponse
breakChain (TNode node
, bool isPreRewrite
) {
81 Assert(isPreRewrite
); // Should be run first
83 Kind k
= node
.getKind();
84 Assert(k
== kind::FLOATINGPOINT_EQ
||
85 k
== kind::FLOATINGPOINT_GEQ
||
86 k
== kind::FLOATINGPOINT_LEQ
||
87 k
== kind::FLOATINGPOINT_GT
||
88 k
== kind::FLOATINGPOINT_LT
);
91 size_t children
= node
.getNumChildren();
94 NodeBuilder
<> conjunction(kind::AND
);
96 for (size_t i
= 0; i
< children
- 1; ++i
) {
97 for (size_t j
= i
+ 1; j
< children
; ++j
) {
98 conjunction
<< NodeManager::currentNM()->mkNode(k
, node
[i
], node
[j
]);
101 return RewriteResponse(REWRITE_AGAIN_FULL
, conjunction
);
104 return RewriteResponse(REWRITE_DONE
, node
);
109 /* Implies (fp.eq x x) --> (not (isNaN x))
112 RewriteResponse
ieeeEqToEq (TNode node
, bool) {
113 Assert(node
.getKind() == kind::FLOATINGPOINT_EQ
);
114 NodeManager
*nm
= NodeManager::currentNM();
116 return RewriteResponse(REWRITE_DONE
,
117 nm
->mkNode(kind::AND
,
118 nm
->mkNode(kind::AND
,
119 nm
->mkNode(kind::NOT
, nm
->mkNode(kind::FLOATINGPOINT_ISNAN
, node
[0])),
120 nm
->mkNode(kind::NOT
, nm
->mkNode(kind::FLOATINGPOINT_ISNAN
, node
[1]))),
122 nm
->mkNode(kind::EQUAL
, node
[0], node
[1]),
123 nm
->mkNode(kind::AND
,
124 nm
->mkNode(kind::FLOATINGPOINT_ISZ
, node
[0]),
125 nm
->mkNode(kind::FLOATINGPOINT_ISZ
, node
[1])))));
129 RewriteResponse
geqToleq (TNode node
, bool) {
130 Assert(node
.getKind() == kind::FLOATINGPOINT_GEQ
);
131 return RewriteResponse(REWRITE_DONE
,NodeManager::currentNM()->mkNode(kind::FLOATINGPOINT_LEQ
,node
[1],node
[0]));
134 RewriteResponse
gtTolt (TNode node
, bool) {
135 Assert(node
.getKind() == kind::FLOATINGPOINT_GT
);
136 return RewriteResponse(REWRITE_DONE
,NodeManager::currentNM()->mkNode(kind::FLOATINGPOINT_LT
,node
[1],node
[0]));
139 RewriteResponse
removed (TNode node
, bool) {
140 Unreachable("kind (%d) should have been removed?",node
.getKind());
141 return RewriteResponse(REWRITE_DONE
, node
);
144 RewriteResponse
variable (TNode node
, bool) {
145 // We should only get floating point and rounding mode variables to rewrite.
146 TypeNode tn
= node
.getType(true);
147 Assert(tn
.isFloatingPoint() || tn
.isRoundingMode());
149 // Not that we do anything with them...
150 return RewriteResponse(REWRITE_DONE
, node
);
153 RewriteResponse
equal (TNode node
, bool isPreRewrite
) {
154 // We should only get equalities of floating point or rounding mode types.
155 Assert(node
.getKind() == kind::EQUAL
);
157 TypeNode tn
= node
[0].getType(true);
159 Assert(tn
.isFloatingPoint() || tn
.isRoundingMode());
160 Assert(tn
== node
[1].getType(true)); // Should be ensured by the typing rules
162 if (node
[0] == node
[1]) {
163 return RewriteResponse(REWRITE_DONE
, NodeManager::currentNM()->mkConst(true));
164 } else if (!isPreRewrite
&& (node
[0] > node
[1])) {
165 Node normal
= NodeManager::currentNM()->mkNode(kind::EQUAL
,node
[1],node
[0]);
166 return RewriteResponse(REWRITE_DONE
, normal
);
168 return RewriteResponse(REWRITE_DONE
, node
);
172 RewriteResponse
convertFromRealLiteral (TNode node
, bool) {
173 Assert(node
.getKind() == kind::FLOATINGPOINT_TO_FP_REAL
);
175 // \todo Honour the rounding mode and work for something other than doubles!
177 if (node
[1].getKind() == kind::CONST_RATIONAL
) {
178 TNode op
= node
.getOperator();
179 const FloatingPointToFPReal
¶m
= op
.getConst
<FloatingPointToFPReal
>();
181 NodeManager::currentNM()->mkConst(FloatingPoint(param
.t
.exponent(),
182 param
.t
.significand(),
183 node
[1].getConst
<Rational
>().getDouble()));
185 return RewriteResponse(REWRITE_DONE
, lit
);
187 return RewriteResponse(REWRITE_DONE
, node
);
191 RewriteResponse
convertFromIEEEBitVectorLiteral (TNode node
, bool) {
192 Assert(node
.getKind() == kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR
);
194 // \todo Handle arbitrary length bit vectors without using strings!
196 if (node
[0].getKind() == kind::CONST_BITVECTOR
) {
197 TNode op
= node
.getOperator();
198 const FloatingPointToFPIEEEBitVector
¶m
= op
.getConst
<FloatingPointToFPIEEEBitVector
>();
199 const BitVector
&bv
= node
[0].getConst
<BitVector
>();
200 std::string
bitString(bv
.toString());
203 NodeManager::currentNM()->mkConst(FloatingPoint(param
.t
.exponent(),
204 param
.t
.significand(),
207 return RewriteResponse(REWRITE_DONE
, lit
);
209 return RewriteResponse(REWRITE_DONE
, node
);
213 RewriteResponse
convertFromLiteral (TNode node
, bool) {
214 Assert(node
.getKind() == kind::FLOATINGPOINT_FP
);
216 // \todo Handle arbitrary length bit vectors without using strings!
218 if ((node
[0].getKind() == kind::CONST_BITVECTOR
) &&
219 (node
[1].getKind() == kind::CONST_BITVECTOR
) &&
220 (node
[2].getKind() == kind::CONST_BITVECTOR
)) {
222 BitVector
bv(node
[0].getConst
<BitVector
>());
223 bv
= bv
.concat(node
[1].getConst
<BitVector
>());
224 bv
= bv
.concat(node
[2].getConst
<BitVector
>());
226 std::string
bitString(bv
.toString());
227 std::reverse(bitString
.begin(), bitString
.end());
229 // +1 to support the hidden bit
231 NodeManager::currentNM()->mkConst(FloatingPoint(node
[1].getConst
<BitVector
>().getSize(),
232 node
[2].getConst
<BitVector
>().getSize() + 1,
235 return RewriteResponse(REWRITE_DONE
, lit
);
237 return RewriteResponse(REWRITE_DONE
, node
);
241 // Note these cannot be assumed to be symmetric for +0/-0, thus no symmetry reorder
242 RewriteResponse
compactMinMax (TNode node
, bool isPreRewrite
) {
243 #ifdef CVC4_ASSERTIONS
244 Kind k
= node
.getKind();
245 Assert((k
== kind::FLOATINGPOINT_MIN
) || (k
== kind::FLOATINGPOINT_MAX
));
247 if (node
[0] == node
[1]) {
248 return RewriteResponse(REWRITE_DONE
, node
[0]);
250 return RewriteResponse(REWRITE_DONE
, node
);
255 RewriteResponse
reorderFPEquality (TNode node
, bool isPreRewrite
) {
256 Assert(node
.getKind() == kind::FLOATINGPOINT_EQ
);
257 Assert(!isPreRewrite
); // Likely redundant in pre-rewrite
259 if (node
[0] > node
[1]) {
260 Node normal
= NodeManager::currentNM()->mkNode(kind::FLOATINGPOINT_EQ
,node
[1],node
[0]);
261 return RewriteResponse(REWRITE_DONE
, normal
);
263 return RewriteResponse(REWRITE_DONE
, node
);
267 RewriteResponse
reorderBinaryOperation (TNode node
, bool isPreRewrite
) {
268 Kind k
= node
.getKind();
269 Assert((k
== kind::FLOATINGPOINT_PLUS
) || (k
== kind::FLOATINGPOINT_MULT
));
270 Assert(!isPreRewrite
); // Likely redundant in pre-rewrite
272 if (node
[1] > node
[2]) {
273 Node normal
= NodeManager::currentNM()->mkNode(k
,node
[0],node
[2],node
[1]);
274 return RewriteResponse(REWRITE_DONE
, normal
);
276 return RewriteResponse(REWRITE_DONE
, node
);
280 RewriteResponse
reorderFMA (TNode node
, bool isPreRewrite
) {
281 Assert(node
.getKind() == kind::FLOATINGPOINT_FMA
);
282 Assert(!isPreRewrite
); // Likely redundant in pre-rewrite
284 if (node
[1] > node
[2]) {
285 Node normal
= NodeManager::currentNM()->mkNode(kind::FLOATINGPOINT_FMA
,node
[0],node
[2],node
[1],node
[3]);
286 return RewriteResponse(REWRITE_DONE
, normal
);
288 return RewriteResponse(REWRITE_DONE
, node
);
292 RewriteResponse
removeSignOperations (TNode node
, bool isPreRewrite
) {
293 Assert(node
.getKind() == kind::FLOATINGPOINT_ISN
||
294 node
.getKind() == kind::FLOATINGPOINT_ISSN
||
295 node
.getKind() == kind::FLOATINGPOINT_ISZ
||
296 node
.getKind() == kind::FLOATINGPOINT_ISINF
||
297 node
.getKind() == kind::FLOATINGPOINT_ISNAN
);
298 Assert(node
.getNumChildren() == 1);
300 Kind
childKind(node
[0].getKind());
302 if ((childKind
== kind::FLOATINGPOINT_NEG
) ||
303 (childKind
== kind::FLOATINGPOINT_ABS
)) {
305 Node rewritten
= NodeManager::currentNM()->mkNode(node
.getKind(),node
[0][0]);
306 return RewriteResponse(REWRITE_AGAIN
, rewritten
);
308 return RewriteResponse(REWRITE_DONE
, node
);
313 }; /* CVC4::theory::fp::rewrite */
315 RewriteFunction
TheoryFpRewriter::preRewriteTable
[kind::LAST_KIND
];
316 RewriteFunction
TheoryFpRewriter::postRewriteTable
[kind::LAST_KIND
];
320 * Initialize the rewriter.
322 void TheoryFpRewriter::init() {
324 /* Set up the pre-rewrite dispatch table */
325 for (unsigned i
= 0; i
< kind::LAST_KIND
; ++i
) {
326 preRewriteTable
[i
] = rewrite::notFP
;
329 /******** Constants ********/
330 /* No rewriting possible for constants */
331 preRewriteTable
[kind::CONST_FLOATINGPOINT
] = rewrite::identity
;
332 preRewriteTable
[kind::CONST_ROUNDINGMODE
] = rewrite::identity
;
334 /******** Sorts(?) ********/
335 /* These kinds should only appear in types */
336 //preRewriteTable[kind::ROUNDINGMODE_TYPE] = rewrite::type;
337 preRewriteTable
[kind::FLOATINGPOINT_TYPE
] = rewrite::type
;
339 /******** Operations ********/
340 preRewriteTable
[kind::FLOATINGPOINT_FP
] = rewrite::identity
;
341 preRewriteTable
[kind::FLOATINGPOINT_ABS
] = rewrite::identity
;
342 preRewriteTable
[kind::FLOATINGPOINT_NEG
] = rewrite::removeDoubleNegation
;
343 preRewriteTable
[kind::FLOATINGPOINT_PLUS
] = rewrite::identity
;
344 preRewriteTable
[kind::FLOATINGPOINT_SUB
] = rewrite::convertSubtractionToAddition
;
345 preRewriteTable
[kind::FLOATINGPOINT_MULT
] = rewrite::identity
;
346 preRewriteTable
[kind::FLOATINGPOINT_DIV
] = rewrite::identity
;
347 preRewriteTable
[kind::FLOATINGPOINT_FMA
] = rewrite::identity
;
348 preRewriteTable
[kind::FLOATINGPOINT_SQRT
] = rewrite::identity
;
349 preRewriteTable
[kind::FLOATINGPOINT_REM
] = rewrite::identity
;
350 preRewriteTable
[kind::FLOATINGPOINT_RTI
] = rewrite::identity
;
351 preRewriteTable
[kind::FLOATINGPOINT_MIN
] = rewrite::compactMinMax
;
352 preRewriteTable
[kind::FLOATINGPOINT_MAX
] = rewrite::compactMinMax
;
354 /******** Comparisons ********/
355 preRewriteTable
[kind::FLOATINGPOINT_EQ
] = rewrite::then
<rewrite::breakChain
,rewrite::ieeeEqToEq
>;
356 preRewriteTable
[kind::FLOATINGPOINT_LEQ
] = rewrite::breakChain
;
357 preRewriteTable
[kind::FLOATINGPOINT_LT
] = rewrite::breakChain
;
358 preRewriteTable
[kind::FLOATINGPOINT_GEQ
] = rewrite::then
<rewrite::breakChain
,rewrite::geqToleq
>;
359 preRewriteTable
[kind::FLOATINGPOINT_GT
] = rewrite::then
<rewrite::breakChain
,rewrite::gtTolt
>;
361 /******** Classifications ********/
362 preRewriteTable
[kind::FLOATINGPOINT_ISN
] = rewrite::identity
;
363 preRewriteTable
[kind::FLOATINGPOINT_ISSN
] = rewrite::identity
;
364 preRewriteTable
[kind::FLOATINGPOINT_ISZ
] = rewrite::identity
;
365 preRewriteTable
[kind::FLOATINGPOINT_ISINF
] = rewrite::identity
;
366 preRewriteTable
[kind::FLOATINGPOINT_ISNAN
] = rewrite::identity
;
367 preRewriteTable
[kind::FLOATINGPOINT_ISNEG
] = rewrite::identity
;
368 preRewriteTable
[kind::FLOATINGPOINT_ISPOS
] = rewrite::identity
;
370 /******** Conversions ********/
371 preRewriteTable
[kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR
] = rewrite::identity
;
372 preRewriteTable
[kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT
] = rewrite::identity
;
373 preRewriteTable
[kind::FLOATINGPOINT_TO_FP_REAL
] = rewrite::identity
;
374 preRewriteTable
[kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR
] = rewrite::identity
;
375 preRewriteTable
[kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR
] = rewrite::identity
;
376 preRewriteTable
[kind::FLOATINGPOINT_TO_FP_GENERIC
] = rewrite::removed
;
377 preRewriteTable
[kind::FLOATINGPOINT_TO_UBV
] = rewrite::identity
;
378 preRewriteTable
[kind::FLOATINGPOINT_TO_SBV
] = rewrite::identity
;
379 preRewriteTable
[kind::FLOATINGPOINT_TO_REAL
] = rewrite::identity
;
381 /******** Variables ********/
382 preRewriteTable
[kind::VARIABLE
] = rewrite::variable
;
383 preRewriteTable
[kind::BOUND_VARIABLE
] = rewrite::variable
;
385 preRewriteTable
[kind::EQUAL
] = rewrite::equal
;
390 /* Set up the post-rewrite dispatch table */
391 for (unsigned i
= 0; i
< kind::LAST_KIND
; ++i
) {
392 postRewriteTable
[i
] = rewrite::notFP
;
395 /******** Constants ********/
396 /* No rewriting possible for constants */
397 postRewriteTable
[kind::CONST_FLOATINGPOINT
] = rewrite::identity
;
398 postRewriteTable
[kind::CONST_ROUNDINGMODE
] = rewrite::identity
;
400 /******** Sorts(?) ********/
401 /* These kinds should only appear in types */
402 //postRewriteTable[kind::ROUNDINGMODE_TYPE] = rewrite::type;
403 postRewriteTable
[kind::FLOATINGPOINT_TYPE
] = rewrite::type
;
405 /******** Operations ********/
406 postRewriteTable
[kind::FLOATINGPOINT_FP
] = rewrite::convertFromLiteral
;
407 postRewriteTable
[kind::FLOATINGPOINT_ABS
] = rewrite::identity
;
408 postRewriteTable
[kind::FLOATINGPOINT_NEG
] = rewrite::removeDoubleNegation
;
409 postRewriteTable
[kind::FLOATINGPOINT_PLUS
] = rewrite::reorderBinaryOperation
;
410 postRewriteTable
[kind::FLOATINGPOINT_SUB
] = rewrite::removed
;
411 postRewriteTable
[kind::FLOATINGPOINT_MULT
] = rewrite::reorderBinaryOperation
;
412 postRewriteTable
[kind::FLOATINGPOINT_DIV
] = rewrite::identity
;
413 postRewriteTable
[kind::FLOATINGPOINT_FMA
] = rewrite::reorderFMA
;
414 postRewriteTable
[kind::FLOATINGPOINT_SQRT
] = rewrite::identity
;
415 postRewriteTable
[kind::FLOATINGPOINT_REM
] = rewrite::identity
;
416 postRewriteTable
[kind::FLOATINGPOINT_RTI
] = rewrite::identity
;
417 postRewriteTable
[kind::FLOATINGPOINT_MIN
] = rewrite::compactMinMax
;
418 postRewriteTable
[kind::FLOATINGPOINT_MAX
] = rewrite::compactMinMax
;
420 /******** Comparisons ********/
421 postRewriteTable
[kind::FLOATINGPOINT_EQ
] = rewrite::removed
;
422 postRewriteTable
[kind::FLOATINGPOINT_LEQ
] = rewrite::identity
;
423 postRewriteTable
[kind::FLOATINGPOINT_LT
] = rewrite::identity
;
424 postRewriteTable
[kind::FLOATINGPOINT_GEQ
] = rewrite::removed
;
425 postRewriteTable
[kind::FLOATINGPOINT_GT
] = rewrite::removed
;
427 /******** Classifications ********/
428 postRewriteTable
[kind::FLOATINGPOINT_ISN
] = rewrite::removeSignOperations
;
429 postRewriteTable
[kind::FLOATINGPOINT_ISSN
] = rewrite::removeSignOperations
;
430 postRewriteTable
[kind::FLOATINGPOINT_ISZ
] = rewrite::removeSignOperations
;
431 postRewriteTable
[kind::FLOATINGPOINT_ISINF
] = rewrite::removeSignOperations
;
432 postRewriteTable
[kind::FLOATINGPOINT_ISNAN
] = rewrite::removeSignOperations
;
433 postRewriteTable
[kind::FLOATINGPOINT_ISNEG
] = rewrite::identity
;
434 postRewriteTable
[kind::FLOATINGPOINT_ISPOS
] = rewrite::identity
;
436 /******** Conversions ********/
437 postRewriteTable
[kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR
] = rewrite::convertFromIEEEBitVectorLiteral
;
438 postRewriteTable
[kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT
] = rewrite::identity
;
439 postRewriteTable
[kind::FLOATINGPOINT_TO_FP_REAL
] = rewrite::convertFromRealLiteral
;
440 postRewriteTable
[kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR
] = rewrite::identity
;
441 postRewriteTable
[kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR
] = rewrite::identity
;
442 postRewriteTable
[kind::FLOATINGPOINT_TO_FP_GENERIC
] = rewrite::removed
;
443 postRewriteTable
[kind::FLOATINGPOINT_TO_UBV
] = rewrite::identity
;
444 postRewriteTable
[kind::FLOATINGPOINT_TO_SBV
] = rewrite::identity
;
445 postRewriteTable
[kind::FLOATINGPOINT_TO_REAL
] = rewrite::identity
;
447 /******** Variables ********/
448 postRewriteTable
[kind::VARIABLE
] = rewrite::variable
;
449 postRewriteTable
[kind::BOUND_VARIABLE
] = rewrite::variable
;
451 postRewriteTable
[kind::EQUAL
] = rewrite::equal
;
460 * Rewrite a node into the normal form for the theory of fp
461 * in pre-order (really topological order)---meaning that the
462 * children may not be in the normal form. This is an optimization
463 * for theories with cancelling terms (e.g., 0 * (big-nasty-expression)
464 * in arithmetic rewrites to 0 without the need to look at the big
465 * nasty expression). Since it's only an optimization, the
466 * implementation here can do nothing.
469 RewriteResponse
TheoryFpRewriter::preRewrite(TNode node
) {
470 Trace("fp-rewrite") << "TheoryFpRewriter::preRewrite(): " << node
<< std::endl
;
471 RewriteResponse res
= preRewriteTable
[node
.getKind()] (node
, true);
472 if (res
.node
!= node
) {
473 Debug("fp-rewrite") << "TheoryFpRewriter::preRewrite(): before " << node
<< std::endl
;
474 Debug("fp-rewrite") << "TheoryFpRewriter::preRewrite(): after " << res
.node
<< std::endl
;
481 * Rewrite a node into the normal form for the theory of fp.
482 * Called in post-order (really reverse-topological order) when
483 * traversing the expression DAG during rewriting. This is the
484 * main function of the rewriter, and because of the ordering,
485 * it can assume its children are all rewritten already.
487 * This function can return one of three rewrite response codes
488 * along with the rewritten node:
490 * REWRITE_DONE indicates that no more rewriting is needed.
491 * REWRITE_AGAIN means that the top-level expression should be
492 * rewritten again, but that its children are in final form.
493 * REWRITE_AGAIN_FULL means that the entire returned expression
494 * should be rewritten again (top-down with preRewrite(), then
495 * bottom-up with postRewrite()).
497 * Even if this function returns REWRITE_DONE, if the returned
498 * expression belongs to a different theory, it will be fully
499 * rewritten by that theory's rewriter.
502 RewriteResponse
TheoryFpRewriter::postRewrite(TNode node
) {
503 Trace("fp-rewrite") << "TheoryFpRewriter::postRewrite(): " << node
<< std::endl
;
504 RewriteResponse res
= postRewriteTable
[node
.getKind()] (node
, false);
505 if (res
.node
!= node
) {
506 Debug("fp-rewrite") << "TheoryFpRewriter::postRewrite(): before " << node
<< std::endl
;
507 Debug("fp-rewrite") << "TheoryFpRewriter::postRewrite(): after " << res
.node
<< std::endl
;
513 }/* CVC4::theory::fp namespace */
514 }/* CVC4::theory namespace */
515 }/* CVC4 namespace */