1 /********************* */
2 /*! \file theory_fp_type_rules.h
4 ** Top contributors (to current version):
5 ** Martin Brain, Tim King, Andres Noetzli
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
8 ** in the top-level source directory and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
12 ** \brief [[ Add one-line brief description here ]]
14 ** [[ Add lengthier description here ]]
15 ** \todo document this file
18 #include "cvc4_private.h"
20 // This is only needed for checking that components are only applied to leaves.
21 #include "theory/theory.h"
22 #include "util/roundingmode.h"
24 #ifndef CVC4__THEORY__FP__THEORY_FP_TYPE_RULES_H
25 #define CVC4__THEORY__FP__THEORY_FP_TYPE_RULES_H
31 #define TRACE(FUNCTION) \
32 Trace("fp-type") << FUNCTION "::computeType(" << check << "): " << n \
35 class FloatingPointConstantTypeRule
{
37 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
39 TRACE("FloatingPointConstantTypeRule");
41 const FloatingPoint
& f
= n
.getConst
<FloatingPoint
>();
45 if (!(validExponentSize(f
.d_fp_size
.exponentWidth())))
47 throw TypeCheckingExceptionPrivate(
48 n
, "constant with invalid exponent size");
50 if (!(validSignificandSize(f
.d_fp_size
.significandWidth())))
52 throw TypeCheckingExceptionPrivate(
53 n
, "constant with invalid significand size");
56 return nodeManager
->mkFloatingPointType(f
.d_fp_size
);
60 class RoundingModeConstantTypeRule
{
62 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
64 TRACE("RoundingModeConstantTypeRule");
67 return nodeManager
->roundingModeType();
71 class FloatingPointFPTypeRule
{
73 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
75 TRACE("FloatingPointFPTypeRule");
77 TypeNode signType
= n
[0].getType(check
);
78 TypeNode exponentType
= n
[1].getType(check
);
79 TypeNode significandType
= n
[2].getType(check
);
81 if (!signType
.isBitVector() || !exponentType
.isBitVector() ||
82 !significandType
.isBitVector()) {
83 throw TypeCheckingExceptionPrivate(n
,
84 "arguments to fp must be bit vectors");
87 unsigned signBits
= signType
.getBitVectorSize();
88 unsigned exponentBits
= exponentType
.getBitVectorSize();
89 unsigned significandBits
= significandType
.getBitVectorSize();
93 throw TypeCheckingExceptionPrivate(
94 n
, "sign bit vector in fp must be 1 bit long");
95 } else if (!(validExponentSize(exponentBits
))) {
96 throw TypeCheckingExceptionPrivate(
97 n
, "exponent bit vector in fp is an invalid size");
98 } else if (!(validSignificandSize(significandBits
))) {
99 throw TypeCheckingExceptionPrivate(
100 n
, "significand bit vector in fp is an invalid size");
104 // The +1 is for the implicit hidden bit
105 return nodeManager
->mkFloatingPointType(exponentBits
, significandBits
+ 1);
109 class FloatingPointTestTypeRule
{
111 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
113 TRACE("FloatingPointTestTypeRule");
116 TypeNode firstOperand
= n
[0].getType(check
);
118 if (!firstOperand
.isFloatingPoint()) {
119 throw TypeCheckingExceptionPrivate(
120 n
, "floating-point test applied to a non floating-point sort");
123 size_t children
= n
.getNumChildren();
124 for (size_t i
= 1; i
< children
; ++i
) {
125 if (!(n
[i
].getType(check
) == firstOperand
)) {
126 throw TypeCheckingExceptionPrivate(
127 n
, "floating-point test applied to mixed sorts");
132 return nodeManager
->booleanType();
136 class FloatingPointOperationTypeRule
{
138 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
140 TRACE("FloatingPointOperationTypeRule");
142 TypeNode firstOperand
= n
[0].getType(check
);
145 if (!firstOperand
.isFloatingPoint()) {
146 throw TypeCheckingExceptionPrivate(
147 n
, "floating-point operation applied to a non floating-point sort");
150 size_t children
= n
.getNumChildren();
151 for (size_t i
= 1; i
< children
; ++i
) {
152 if (!(n
[i
].getType(check
) == firstOperand
)) {
153 throw TypeCheckingExceptionPrivate(
154 n
, "floating-point test applied to mixed sorts");
163 class FloatingPointRoundingOperationTypeRule
{
165 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
167 TRACE("FloatingPointRoundingOperationTypeRule");
170 TypeNode roundingModeType
= n
[0].getType(check
);
172 if (!roundingModeType
.isRoundingMode()) {
173 throw TypeCheckingExceptionPrivate(
174 n
, "first argument must be a rounding mode");
178 TypeNode firstOperand
= n
[1].getType(check
);
181 if (!firstOperand
.isFloatingPoint()) {
182 throw TypeCheckingExceptionPrivate(
183 n
, "floating-point operation applied to a non floating-point sort");
186 size_t children
= n
.getNumChildren();
187 for (size_t i
= 2; i
< children
; ++i
) {
188 if (!(n
[i
].getType(check
) == firstOperand
)) {
189 throw TypeCheckingExceptionPrivate(
190 n
, "floating-point operation applied to mixed sorts");
199 class FloatingPointPartialOperationTypeRule
{
201 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
203 TRACE("FloatingPointOperationTypeRule");
204 AlwaysAssert(n
.getNumChildren() > 0);
206 TypeNode firstOperand
= n
[0].getType(check
);
209 if (!firstOperand
.isFloatingPoint()) {
210 throw TypeCheckingExceptionPrivate(
211 n
, "floating-point operation applied to a non floating-point sort");
214 const size_t children
= n
.getNumChildren();
215 for (size_t i
= 1; i
< children
- 1; ++i
) {
216 if (n
[i
].getType(check
) != firstOperand
) {
217 throw TypeCheckingExceptionPrivate(
218 n
, "floating-point partial operation applied to mixed sorts");
222 TypeNode UFValueType
= n
[children
- 1].getType(check
);
224 if (!(UFValueType
.isBitVector()) ||
225 !(UFValueType
.getBitVectorSize() == 1)) {
226 throw TypeCheckingExceptionPrivate(
227 n
, "floating-point partial operation final argument must be a bit-vector of length 1");
236 class FloatingPointParametricOpTypeRule
{
238 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
240 TRACE("FloatingPointParametricOpTypeRule");
242 return nodeManager
->builtinOperatorType();
246 class FloatingPointToFPIEEEBitVectorTypeRule
{
248 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
250 TRACE("FloatingPointToFPIEEEBitVectorTypeRule");
251 AlwaysAssert(n
.getNumChildren() == 1);
253 FloatingPointToFPIEEEBitVector info
=
254 n
.getOperator().getConst
<FloatingPointToFPIEEEBitVector
>();
257 TypeNode operandType
= n
[0].getType(check
);
259 if (!(operandType
.isBitVector()))
261 throw TypeCheckingExceptionPrivate(n
,
262 "conversion to floating-point from "
263 "bit vector used with sort other "
266 else if (!(operandType
.getBitVectorSize()
267 == info
.d_fp_size
.exponentWidth()
268 + info
.d_fp_size
.significandWidth()))
270 throw TypeCheckingExceptionPrivate(
272 "conversion to floating-point from bit vector used with bit vector "
273 "length that does not match floating point parameters");
277 return nodeManager
->mkFloatingPointType(info
.d_fp_size
);
281 class FloatingPointToFPFloatingPointTypeRule
{
283 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
285 TRACE("FloatingPointToFPFloatingPointTypeRule");
286 AlwaysAssert(n
.getNumChildren() == 2);
288 FloatingPointToFPFloatingPoint info
=
289 n
.getOperator().getConst
<FloatingPointToFPFloatingPoint
>();
292 TypeNode roundingModeType
= n
[0].getType(check
);
294 if (!roundingModeType
.isRoundingMode()) {
295 throw TypeCheckingExceptionPrivate(
296 n
, "first argument must be a rounding mode");
299 TypeNode operandType
= n
[1].getType(check
);
301 if (!(operandType
.isFloatingPoint())) {
302 throw TypeCheckingExceptionPrivate(n
,
303 "conversion to floating-point from "
304 "floating-point used with sort "
305 "other than floating-point");
309 return nodeManager
->mkFloatingPointType(info
.d_fp_size
);
313 class FloatingPointToFPRealTypeRule
{
315 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
317 TRACE("FloatingPointToFPRealTypeRule");
318 AlwaysAssert(n
.getNumChildren() == 2);
320 FloatingPointToFPReal info
=
321 n
.getOperator().getConst
<FloatingPointToFPReal
>();
324 TypeNode roundingModeType
= n
[0].getType(check
);
326 if (!roundingModeType
.isRoundingMode()) {
327 throw TypeCheckingExceptionPrivate(
328 n
, "first argument must be a rounding mode");
331 TypeNode operandType
= n
[1].getType(check
);
333 if (!(operandType
.isReal())) {
334 throw TypeCheckingExceptionPrivate(n
,
335 "conversion to floating-point from "
336 "real used with sort other than "
341 return nodeManager
->mkFloatingPointType(info
.d_fp_size
);
345 class FloatingPointToFPSignedBitVectorTypeRule
{
347 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
349 TRACE("FloatingPointToFPSignedBitVectorTypeRule");
350 AlwaysAssert(n
.getNumChildren() == 2);
352 FloatingPointToFPSignedBitVector info
=
353 n
.getOperator().getConst
<FloatingPointToFPSignedBitVector
>();
356 TypeNode roundingModeType
= n
[0].getType(check
);
358 if (!roundingModeType
.isRoundingMode()) {
359 throw TypeCheckingExceptionPrivate(
360 n
, "first argument must be a rounding mode");
363 TypeNode operandType
= n
[1].getType(check
);
365 if (!(operandType
.isBitVector())) {
366 throw TypeCheckingExceptionPrivate(n
,
367 "conversion to floating-point from "
368 "signed bit vector used with sort "
369 "other than bit vector");
373 return nodeManager
->mkFloatingPointType(info
.d_fp_size
);
377 class FloatingPointToFPUnsignedBitVectorTypeRule
{
379 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
381 TRACE("FloatingPointToFPUnsignedBitVectorTypeRule");
382 AlwaysAssert(n
.getNumChildren() == 2);
384 FloatingPointToFPUnsignedBitVector info
=
385 n
.getOperator().getConst
<FloatingPointToFPUnsignedBitVector
>();
388 TypeNode roundingModeType
= n
[0].getType(check
);
390 if (!roundingModeType
.isRoundingMode()) {
391 throw TypeCheckingExceptionPrivate(
392 n
, "first argument must be a rounding mode");
395 TypeNode operandType
= n
[1].getType(check
);
397 if (!(operandType
.isBitVector())) {
398 throw TypeCheckingExceptionPrivate(n
,
399 "conversion to floating-point from "
400 "unsigned bit vector used with sort "
401 "other than bit vector");
405 return nodeManager
->mkFloatingPointType(info
.d_fp_size
);
409 class FloatingPointToFPGenericTypeRule
{
411 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
413 TRACE("FloatingPointToFPGenericTypeRule");
415 FloatingPointToFPGeneric info
=
416 n
.getOperator().getConst
<FloatingPointToFPGeneric
>();
419 /* As this is a generic kind intended only for parsing,
420 * the checking here is light. For better checking, use
421 * expandDefinitions first.
424 size_t children
= n
.getNumChildren();
425 for (size_t i
= 0; i
< children
; ++i
) {
430 return nodeManager
->mkFloatingPointType(info
.d_fp_size
);
434 class FloatingPointToUBVTypeRule
{
436 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
438 TRACE("FloatingPointToUBVTypeRule");
439 AlwaysAssert(n
.getNumChildren() == 2);
441 FloatingPointToUBV info
= n
.getOperator().getConst
<FloatingPointToUBV
>();
444 TypeNode roundingModeType
= n
[0].getType(check
);
446 if (!roundingModeType
.isRoundingMode()) {
447 throw TypeCheckingExceptionPrivate(
448 n
, "first argument must be a rounding mode");
451 TypeNode operandType
= n
[1].getType(check
);
453 if (!(operandType
.isFloatingPoint())) {
454 throw TypeCheckingExceptionPrivate(n
,
455 "conversion to unsigned bit vector "
456 "used with a sort other than "
461 return nodeManager
->mkBitVectorType(info
.d_bv_size
);
465 class FloatingPointToSBVTypeRule
{
467 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
469 TRACE("FloatingPointToSBVTypeRule");
470 AlwaysAssert(n
.getNumChildren() == 2);
472 FloatingPointToSBV info
= n
.getOperator().getConst
<FloatingPointToSBV
>();
475 TypeNode roundingModeType
= n
[0].getType(check
);
477 if (!roundingModeType
.isRoundingMode()) {
478 throw TypeCheckingExceptionPrivate(
479 n
, "first argument must be a rounding mode");
482 TypeNode operandType
= n
[1].getType(check
);
484 if (!(operandType
.isFloatingPoint())) {
485 throw TypeCheckingExceptionPrivate(n
,
486 "conversion to signed bit vector "
487 "used with a sort other than "
492 return nodeManager
->mkBitVectorType(info
.d_bv_size
);
496 class FloatingPointToUBVTotalTypeRule
{
498 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
500 TRACE("FloatingPointToUBVTotalTypeRule");
501 AlwaysAssert(n
.getNumChildren() == 3);
503 FloatingPointToUBVTotal info
= n
.getOperator().getConst
<FloatingPointToUBVTotal
>();
506 TypeNode roundingModeType
= n
[0].getType(check
);
508 if (!roundingModeType
.isRoundingMode()) {
509 throw TypeCheckingExceptionPrivate(
510 n
, "first argument must be a rounding mode");
513 TypeNode operandType
= n
[1].getType(check
);
515 if (!(operandType
.isFloatingPoint())) {
516 throw TypeCheckingExceptionPrivate(n
,
517 "conversion to unsigned bit vector total"
518 "used with a sort other than "
522 TypeNode defaultValueType
= n
[2].getType(check
);
524 if (!(defaultValueType
.isBitVector()) ||
525 !(defaultValueType
.getBitVectorSize() == info
)) {
526 throw TypeCheckingExceptionPrivate(n
,
527 "conversion to unsigned bit vector total"
528 "needs a bit vector of the same length"
533 return nodeManager
->mkBitVectorType(info
.d_bv_size
);
537 class FloatingPointToSBVTotalTypeRule
{
539 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
541 TRACE("FloatingPointToSBVTotalTypeRule");
542 AlwaysAssert(n
.getNumChildren() == 3);
544 FloatingPointToSBVTotal info
= n
.getOperator().getConst
<FloatingPointToSBVTotal
>();
547 TypeNode roundingModeType
= n
[0].getType(check
);
549 if (!roundingModeType
.isRoundingMode()) {
550 throw TypeCheckingExceptionPrivate(
551 n
, "first argument must be a rounding mode");
554 TypeNode operandType
= n
[1].getType(check
);
556 if (!(operandType
.isFloatingPoint())) {
557 throw TypeCheckingExceptionPrivate(n
,
558 "conversion to signed bit vector "
559 "used with a sort other than "
563 TypeNode defaultValueType
= n
[2].getType(check
);
565 if (!(defaultValueType
.isBitVector()) ||
566 !(defaultValueType
.getBitVectorSize() == info
)) {
567 throw TypeCheckingExceptionPrivate(n
,
568 "conversion to signed bit vector total"
569 "needs a bit vector of the same length"
574 return nodeManager
->mkBitVectorType(info
.d_bv_size
);
578 class FloatingPointToRealTypeRule
{
580 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
582 TRACE("FloatingPointToRealTypeRule");
583 AlwaysAssert(n
.getNumChildren() == 1);
586 TypeNode operandType
= n
[0].getType(check
);
588 if (!operandType
.isFloatingPoint()) {
589 throw TypeCheckingExceptionPrivate(
590 n
, "floating-point to real applied to a non floating-point sort");
594 return nodeManager
->realType();
598 class FloatingPointToRealTotalTypeRule
{
600 inline static TypeNode
computeType(NodeManager
* nodeManager
, TNode n
,
602 TRACE("FloatingPointToRealTotalTypeRule");
603 AlwaysAssert(n
.getNumChildren() == 2);
606 TypeNode operandType
= n
[0].getType(check
);
608 if (!operandType
.isFloatingPoint()) {
609 throw TypeCheckingExceptionPrivate(
610 n
, "floating-point to real total applied to a non floating-point sort");
613 TypeNode defaultValueType
= n
[1].getType(check
);
615 if (!defaultValueType
.isReal()) {
616 throw TypeCheckingExceptionPrivate(
617 n
, "floating-point to real total needs a real second argument");
622 return nodeManager
->realType();
626 class FloatingPointComponentBit
629 inline static TypeNode
computeType(NodeManager
* nodeManager
,
633 TRACE("FloatingPointComponentBit");
637 TypeNode operandType
= n
[0].getType(check
);
639 if (!operandType
.isFloatingPoint())
641 throw TypeCheckingExceptionPrivate(n
,
642 "floating-point bit component "
643 "applied to a non floating-point "
646 if (!(Theory::isLeafOf(n
[0], THEORY_FP
)
647 || n
[0].getKind() == kind::FLOATINGPOINT_TO_FP_REAL
))
649 throw TypeCheckingExceptionPrivate(n
,
650 "floating-point bit component "
651 "applied to a non leaf / to_fp leaf "
656 return nodeManager
->mkBitVectorType(1);
660 class FloatingPointComponentExponent
663 inline static TypeNode
computeType(NodeManager
* nodeManager
,
667 TRACE("FloatingPointComponentExponent");
669 TypeNode operandType
= n
[0].getType(check
);
673 if (!operandType
.isFloatingPoint())
675 throw TypeCheckingExceptionPrivate(n
,
676 "floating-point exponent component "
677 "applied to a non floating-point "
680 if (!(Theory::isLeafOf(n
[0], THEORY_FP
)
681 || n
[0].getKind() == kind::FLOATINGPOINT_TO_FP_REAL
))
683 throw TypeCheckingExceptionPrivate(n
,
684 "floating-point exponent component "
685 "applied to a non leaf / to_fp "
690 #ifdef CVC4_USE_SYMFPU
691 /* Need to create some symfpu objects as the size of bit-vector
692 * that is needed for this component is dependent on the encoding
693 * used (i.e. whether subnormals are forcibly normalised or not).
694 * Here we use types from floatingpoint.h which are the literal
695 * back-end but it should't make a difference. */
696 FloatingPointSize fps
= operandType
.getConst
<FloatingPointSize
>();
697 unsigned bw
= FloatingPoint::getUnpackedExponentWidth(fps
);
701 return nodeManager
->mkBitVectorType(bw
);
705 class FloatingPointComponentSignificand
708 inline static TypeNode
computeType(NodeManager
* nodeManager
,
712 TRACE("FloatingPointComponentSignificand");
714 TypeNode operandType
= n
[0].getType(check
);
718 if (!operandType
.isFloatingPoint())
720 throw TypeCheckingExceptionPrivate(n
,
721 "floating-point significand "
722 "component applied to a non "
723 "floating-point sort");
725 if (!(Theory::isLeafOf(n
[0], THEORY_FP
)
726 || n
[0].getKind() == kind::FLOATINGPOINT_TO_FP_REAL
))
728 throw TypeCheckingExceptionPrivate(n
,
729 "floating-point significand "
730 "component applied to a non leaf / "
735 #ifdef CVC4_USE_SYMFPU
736 /* As before we need to use some of sympfu. */
737 FloatingPointSize fps
= operandType
.getConst
<FloatingPointSize
>();
738 unsigned bw
= FloatingPoint::getUnpackedSignificandWidth(fps
);
742 return nodeManager
->mkBitVectorType(bw
);
746 class RoundingModeBitBlast
749 inline static TypeNode
computeType(NodeManager
* nodeManager
,
753 TRACE("RoundingModeBitBlast");
757 TypeNode operandType
= n
[0].getType(check
);
759 if (!operandType
.isRoundingMode())
761 throw TypeCheckingExceptionPrivate(
762 n
, "rounding mode bit-blast applied to a non rounding-mode sort");
764 if (!Theory::isLeafOf(n
[0], THEORY_FP
))
766 throw TypeCheckingExceptionPrivate(
767 n
, "rounding mode bit-blast applied to a non leaf node");
771 return nodeManager
->mkBitVectorType(CVC4_NUM_ROUNDING_MODES
);
775 class CardinalityComputer
{
777 inline static Cardinality
computeCardinality(TypeNode type
) {
778 Assert(type
.getKind() == kind::FLOATINGPOINT_TYPE
);
780 FloatingPointSize fps
= type
.getConst
<FloatingPointSize
>();
786 * 2*2^(s-1) Subnormal
787 * 2*((2^e)-2)*2^(s-1) Normal
789 * = 1 + 2*2 + 2*((2^e)-1)*2^(s-1)
790 * = 5 + ((2^e)-1)*2^s
793 Integer significandValues
= Integer(2).pow(fps
.significandWidth());
794 Integer exponentValues
= Integer(2).pow(fps
.exponentWidth());
795 exponentValues
-= Integer(1);
797 return Integer(5) + exponentValues
* significandValues
;
799 };/* class CardinalityComputer */
804 }/* CVC4::theory::fp namespace */
805 }/* CVC4::theory namespace */
806 }/* CVC4 namespace */
808 #endif /* CVC4__THEORY__FP__THEORY_FP_TYPE_RULES_H */