GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/fp/fp_word_blaster.cpp Lines: 521 596 87.4 %
Date: 2021-09-29 Branches: 1398 4249 32.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Martin Brain, Mathias Preiner, Aina Niemetz
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 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.
11
 * ****************************************************************************
12
 *
13
 * Conversion of floating-point operations to bit-vectors using symfpu.
14
 */
15
16
#include "theory/fp/fp_word_blaster.h"
17
18
#include <vector>
19
20
#include "base/check.h"
21
#include "expr/node_builder.h"
22
#include "symfpu/core/add.h"
23
#include "symfpu/core/classify.h"
24
#include "symfpu/core/compare.h"
25
#include "symfpu/core/convert.h"
26
#include "symfpu/core/divide.h"
27
#include "symfpu/core/fma.h"
28
#include "symfpu/core/ite.h"
29
#include "symfpu/core/multiply.h"
30
#include "symfpu/core/packing.h"
31
#include "symfpu/core/remainder.h"
32
#include "symfpu/core/sign.h"
33
#include "symfpu/core/sqrt.h"
34
#include "symfpu/utils/numberOfRoundingModes.h"
35
#include "symfpu/utils/properties.h"
36
#include "theory/theory.h"  // theory.h Only needed for the leaf test
37
#include "util/floatingpoint.h"
38
#include "util/floatingpoint_literal_symfpu.h"
39
40
namespace symfpu {
41
using namespace ::cvc5::theory::fp::symfpuSymbolic;
42
43
#define CVC5_SYM_ITE_DFN(T)                                                \
44
  template <>                                                              \
45
  struct ite<symbolicProposition, T>                                       \
46
  {                                                                        \
47
    static const T iteOp(const symbolicProposition& _cond,                 \
48
                         const T& _l,                                      \
49
                         const T& _r)                                      \
50
    {                                                                      \
51
      ::cvc5::NodeManager* nm = ::cvc5::NodeManager::currentNM();          \
52
                                                                           \
53
      ::cvc5::Node cond = _cond;                                           \
54
      ::cvc5::Node l = _l;                                                 \
55
      ::cvc5::Node r = _r;                                                 \
56
                                                                           \
57
      /* Handle some common symfpu idioms */                               \
58
      if (cond.isConst())                                                  \
59
      {                                                                    \
60
        return (cond == nm->mkConst(::cvc5::BitVector(1U, 1U))) ? l : r;   \
61
      }                                                                    \
62
      else                                                                 \
63
      {                                                                    \
64
        if (l.getKind() == ::cvc5::kind::BITVECTOR_ITE)                    \
65
        {                                                                  \
66
          if (l[1] == r)                                                   \
67
          {                                                                \
68
            return nm->mkNode(                                             \
69
                ::cvc5::kind::BITVECTOR_ITE,                               \
70
                nm->mkNode(::cvc5::kind::BITVECTOR_AND,                    \
71
                           cond,                                           \
72
                           nm->mkNode(::cvc5::kind::BITVECTOR_NOT, l[0])), \
73
                l[2],                                                      \
74
                r);                                                        \
75
          }                                                                \
76
          else if (l[2] == r)                                              \
77
          {                                                                \
78
            return nm->mkNode(                                             \
79
                ::cvc5::kind::BITVECTOR_ITE,                               \
80
                nm->mkNode(::cvc5::kind::BITVECTOR_AND, cond, l[0]),       \
81
                l[1],                                                      \
82
                r);                                                        \
83
          }                                                                \
84
        }                                                                  \
85
        else if (r.getKind() == ::cvc5::kind::BITVECTOR_ITE)               \
86
        {                                                                  \
87
          if (r[1] == l)                                                   \
88
          {                                                                \
89
            return nm->mkNode(                                             \
90
                ::cvc5::kind::BITVECTOR_ITE,                               \
91
                nm->mkNode(::cvc5::kind::BITVECTOR_AND,                    \
92
                           nm->mkNode(::cvc5::kind::BITVECTOR_NOT, cond),  \
93
                           nm->mkNode(::cvc5::kind::BITVECTOR_NOT, r[0])), \
94
                r[2],                                                      \
95
                l);                                                        \
96
          }                                                                \
97
          else if (r[2] == l)                                              \
98
          {                                                                \
99
            return nm->mkNode(                                             \
100
                ::cvc5::kind::BITVECTOR_ITE,                               \
101
                nm->mkNode(::cvc5::kind::BITVECTOR_AND,                    \
102
                           nm->mkNode(::cvc5::kind::BITVECTOR_NOT, cond),  \
103
                           r[0]),                                          \
104
                r[1],                                                      \
105
                l);                                                        \
106
          }                                                                \
107
        }                                                                  \
108
      }                                                                    \
109
      return T(nm->mkNode(::cvc5::kind::BITVECTOR_ITE, cond, l, r));       \
110
    }                                                                      \
111
  }
112
113
// Can (unsurprisingly) only ITE things which contain Nodes
114
CVC5_SYM_ITE_DFN(traits::rm);
115
4238
CVC5_SYM_ITE_DFN(traits::prop);
116
6591
CVC5_SYM_ITE_DFN(traits::sbv);
117
12504
CVC5_SYM_ITE_DFN(traits::ubv);
118
119
#undef CVC5_SYM_ITE_DFN
120
121
template <>
122
3814
traits::ubv orderEncode<traits, traits::ubv>(const traits::ubv& b)
123
{
124
3814
  return orderEncodeBitwise<traits, traits::ubv>(b);
125
}
126
127
template <>
128
25
stickyRightShiftResult<traits> stickyRightShift(const traits::ubv& input,
129
                                                const traits::ubv& shiftAmount)
130
{
131
25
  return stickyRightShiftBitwise<traits>(input, shiftAmount);
132
}
133
134
template <>
135
6000
void probabilityAnnotation<traits, traits::prop>(const traits::prop& p,
136
                                                 const probability& pr)
137
{
138
  // For now, do nothing...
139
6000
  return;
140
}
141
};  // namespace symfpu
142
143
namespace cvc5 {
144
namespace theory {
145
namespace fp {
146
namespace symfpuSymbolic {
147
148
244
symbolicRoundingMode traits::RNE(void) { return symbolicRoundingMode(0x01); };
149
225
symbolicRoundingMode traits::RNA(void) { return symbolicRoundingMode(0x02); };
150
226
symbolicRoundingMode traits::RTP(void) { return symbolicRoundingMode(0x04); };
151
276
symbolicRoundingMode traits::RTN(void) { return symbolicRoundingMode(0x08); };
152
181
symbolicRoundingMode traits::RTZ(void) { return symbolicRoundingMode(0x10); };
153
154
5368
void traits::precondition(const bool b)
155
{
156
5368
  Assert(b);
157
5368
  return;
158
}
159
2025
void traits::postcondition(const bool b)
160
{
161
2025
  Assert(b);
162
2025
  return;
163
}
164
68903
void traits::invariant(const bool b)
165
{
166
68903
  Assert(b);
167
68903
  return;
168
}
169
170
4261
void traits::precondition(const prop& p) { return; }
171
4237
void traits::postcondition(const prop& p) { return; }
172
11837
void traits::invariant(const prop& p) { return; }
173
// This allows us to use the symfpu literal / symbolic assertions in the
174
// symbolic back-end
175
typedef traits t;
176
177
430530
bool symbolicProposition::checkNodeType(const TNode node)
178
{
179
861060
  TypeNode tn = node.getType(false);
180
861060
  return tn.isBitVector() && tn.getBitVectorSize() == 1;
181
}
182
183
405523
symbolicProposition::symbolicProposition(const Node n) : nodeWrapper(n)
184
{
185
405523
  Assert(checkNodeType(*this));
186
405523
}  // Only used within this header so could be friend'd
187
15584
symbolicProposition::symbolicProposition(bool v)
188
    : nodeWrapper(
189
15584
        NodeManager::currentNM()->mkConst(BitVector(1U, (v ? 1U : 0U))))
190
{
191
15584
  Assert(checkNodeType(*this));
192
15584
}
193
194
9423
symbolicProposition::symbolicProposition(const symbolicProposition& old)
195
9423
    : nodeWrapper(old)
196
{
197
9423
  Assert(checkNodeType(*this));
198
9423
}
199
200
47597
symbolicProposition symbolicProposition::operator!(void) const
201
{
202
  return symbolicProposition(
203
47597
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, *this));
204
}
205
206
65054
symbolicProposition symbolicProposition::operator&&(
207
    const symbolicProposition& op) const
208
{
209
  return symbolicProposition(
210
65054
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_AND, *this, op));
211
}
212
213
96322
symbolicProposition symbolicProposition::operator||(
214
    const symbolicProposition& op) const
215
{
216
  return symbolicProposition(
217
96322
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_OR, *this, op));
218
}
219
220
7088
symbolicProposition symbolicProposition::operator==(
221
    const symbolicProposition& op) const
222
{
223
  return symbolicProposition(
224
7088
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_COMP, *this, op));
225
}
226
227
168
symbolicProposition symbolicProposition::operator^(
228
    const symbolicProposition& op) const
229
{
230
  return symbolicProposition(
231
168
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_XOR, *this, op));
232
}
233
234
1232
bool symbolicRoundingMode::checkNodeType(const TNode n)
235
{
236
1232
  return n.getType(false).isBitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES);
237
}
238
239
18
symbolicRoundingMode::symbolicRoundingMode(const Node n) : nodeWrapper(n)
240
{
241
18
  Assert(checkNodeType(*this));
242
18
}
243
244
1152
symbolicRoundingMode::symbolicRoundingMode(const unsigned v)
245
3456
    : nodeWrapper(NodeManager::currentNM()->mkConst(
246
4608
        BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, v)))
247
{
248
1152
  Assert((v & (v - 1)) == 0 && v != 0);  // Exactly one bit set
249
1152
  Assert(checkNodeType(*this));
250
1152
}
251
252
62
symbolicRoundingMode::symbolicRoundingMode(const symbolicRoundingMode& old)
253
62
    : nodeWrapper(old)
254
{
255
62
  Assert(checkNodeType(*this));
256
62
}
257
258
18
symbolicProposition symbolicRoundingMode::valid(void) const
259
{
260
18
  NodeManager* nm = NodeManager::currentNM();
261
36
  Node zero(nm->mkConst(BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, 0u)));
262
263
  // Is there a better encoding of this?
264
72
  return symbolicProposition(nm->mkNode(
265
      kind::BITVECTOR_AND,
266
72
      nm->mkNode(
267
          kind::BITVECTOR_COMP,
268
36
          nm->mkNode(kind::BITVECTOR_AND,
269
                     *this,
270
36
                     nm->mkNode(kind::BITVECTOR_SUB,
271
                                *this,
272
36
                                nm->mkConst(BitVector(
273
                                    SYMFPU_NUMBER_OF_ROUNDING_MODES, 1u)))),
274
          zero),
275
36
      nm->mkNode(kind::BITVECTOR_NOT,
276
72
                 nm->mkNode(kind::BITVECTOR_COMP, *this, zero))));
277
}
278
279
748
symbolicProposition symbolicRoundingMode::operator==(
280
    const symbolicRoundingMode& op) const
281
{
282
  return symbolicProposition(
283
748
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_COMP, *this, op));
284
}
285
286
template <bool isSigned>
287
Node symbolicBitVector<isSigned>::boolNodeToBV(Node node) const
288
{
289
  Assert(node.getType().isBoolean());
290
  NodeManager* nm = NodeManager::currentNM();
291
  return nm->mkNode(kind::ITE,
292
                    node,
293
                    nm->mkConst(BitVector(1U, 1U)),
294
                    nm->mkConst(BitVector(1U, 0U)));
295
}
296
297
template <bool isSigned>
298
Node symbolicBitVector<isSigned>::BVToBoolNode(Node node) const
299
{
300
  Assert(node.getType().isBitVector());
301
  Assert(node.getType().getBitVectorSize() == 1);
302
  NodeManager* nm = NodeManager::currentNM();
303
  return nm->mkNode(kind::EQUAL, node, nm->mkConst(BitVector(1U, 1U)));
304
}
305
306
template <bool isSigned>
307
72936
Node symbolicBitVector<isSigned>::fromProposition(Node node) const
308
{
309
72936
  return node;
310
}
311
template <bool isSigned>
312
Node symbolicBitVector<isSigned>::toProposition(Node node) const
313
{
314
  return boolNodeToBV(node);
315
}
316
317
template <bool isSigned>
318
493065
symbolicBitVector<isSigned>::symbolicBitVector(const Node n) : nodeWrapper(n)
319
{
320
493065
  Assert(checkNodeType(*this));
321
493065
}
322
323
template <bool isSigned>
324
737161
bool symbolicBitVector<isSigned>::checkNodeType(const TNode n)
325
{
326
737161
  return n.getType(false).isBitVector();
327
}
328
329
template <bool isSigned>
330
231426
symbolicBitVector<isSigned>::symbolicBitVector(const bwt w, const unsigned v)
331
231426
    : nodeWrapper(NodeManager::currentNM()->mkConst(BitVector(w, v)))
332
{
333
231426
  Assert(checkNodeType(*this));
334
231426
}
335
template <bool isSigned>
336
72936
symbolicBitVector<isSigned>::symbolicBitVector(const symbolicProposition& p)
337
72936
    : nodeWrapper(fromProposition(p))
338
{
339
72936
}
340
template <bool isSigned>
341
12254
symbolicBitVector<isSigned>::symbolicBitVector(
342
    const symbolicBitVector<isSigned>& old)
343
12254
    : nodeWrapper(old)
344
{
345
12254
  Assert(checkNodeType(*this));
346
12254
}
347
template <bool isSigned>
348
416
symbolicBitVector<isSigned>::symbolicBitVector(const BitVector& old)
349
416
    : nodeWrapper(NodeManager::currentNM()->mkConst(old))
350
{
351
416
  Assert(checkNodeType(*this));
352
416
}
353
354
template <bool isSigned>
355
67600
bwt symbolicBitVector<isSigned>::getWidth(void) const
356
{
357
67600
  return this->getType(false).getBitVectorSize();
358
}
359
360
/*** Constant creation and test ***/
361
template <bool isSigned>
362
69093
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::one(const bwt& w)
363
{
364
69093
  return symbolicBitVector<isSigned>(w, 1);
365
}
366
template <bool isSigned>
367
30429
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::zero(const bwt& w)
368
{
369
30429
  return symbolicBitVector<isSigned>(w, 0);
370
}
371
template <bool isSigned>
372
3568
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::allOnes(const bwt& w)
373
{
374
3568
  return symbolicBitVector<isSigned>(~zero(w));
375
}
376
377
template <bool isSigned>
378
1256
symbolicProposition symbolicBitVector<isSigned>::isAllOnes() const
379
{
380
1256
  return (*this == symbolicBitVector<isSigned>::allOnes(this->getWidth()));
381
}
382
template <bool isSigned>
383
8627
symbolicProposition symbolicBitVector<isSigned>::isAllZeros() const
384
{
385
8627
  return (*this == symbolicBitVector<isSigned>::zero(this->getWidth()));
386
}
387
388
template <>
389
49
symbolicBitVector<true> symbolicBitVector<true>::maxValue(const bwt& w)
390
{
391
98
  symbolicBitVector<true> leadingZero(symbolicBitVector<true>::zero(1));
392
98
  symbolicBitVector<true> base(symbolicBitVector<true>::allOnes(w - 1));
393
394
98
  return symbolicBitVector<true>(::cvc5::NodeManager::currentNM()->mkNode(
395
98
      ::cvc5::kind::BITVECTOR_CONCAT, leadingZero, base));
396
}
397
398
template <>
399
1
symbolicBitVector<false> symbolicBitVector<false>::maxValue(const bwt& w)
400
{
401
1
  return symbolicBitVector<false>::allOnes(w);
402
}
403
404
template <>
405
6
symbolicBitVector<true> symbolicBitVector<true>::minValue(const bwt& w)
406
{
407
12
  symbolicBitVector<true> leadingOne(symbolicBitVector<true>::one(1));
408
12
  symbolicBitVector<true> base(symbolicBitVector<true>::zero(w - 1));
409
410
12
  return symbolicBitVector<true>(::cvc5::NodeManager::currentNM()->mkNode(
411
12
      ::cvc5::kind::BITVECTOR_CONCAT, leadingOne, base));
412
}
413
414
template <>
415
symbolicBitVector<false> symbolicBitVector<false>::minValue(const bwt& w)
416
{
417
  return symbolicBitVector<false>::zero(w);
418
}
419
420
/*** Operators ***/
421
template <bool isSigned>
422
51645
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator<<(
423
    const symbolicBitVector<isSigned>& op) const
424
{
425
  return symbolicBitVector<isSigned>(
426
51645
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_SHL, *this, op));
427
}
428
429
template <bool isSigned>
430
2047
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator>>(
431
    const symbolicBitVector<isSigned>& op) const
432
{
433
  return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
434
2047
      (isSigned) ? kind::BITVECTOR_ASHR : kind::BITVECTOR_LSHR, *this, op));
435
}
436
437
template <bool isSigned>
438
66959
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator|(
439
    const symbolicBitVector<isSigned>& op) const
440
{
441
  return symbolicBitVector<isSigned>(
442
66959
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_OR, *this, op));
443
}
444
445
template <bool isSigned>
446
8095
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator&(
447
    const symbolicBitVector<isSigned>& op) const
448
{
449
  return symbolicBitVector<isSigned>(
450
8095
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_AND, *this, op));
451
}
452
453
template <bool isSigned>
454
2794
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator+(
455
    const symbolicBitVector<isSigned>& op) const
456
{
457
  return symbolicBitVector<isSigned>(
458
2794
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_ADD, *this, op));
459
}
460
461
template <bool isSigned>
462
65831
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator-(
463
    const symbolicBitVector<isSigned>& op) const
464
{
465
  return symbolicBitVector<isSigned>(
466
65831
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_SUB, *this, op));
467
}
468
469
template <bool isSigned>
470
24
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator*(
471
    const symbolicBitVector<isSigned>& op) const
472
{
473
  return symbolicBitVector<isSigned>(
474
24
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_MULT, *this, op));
475
}
476
477
template <bool isSigned>
478
6
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator/(
479
    const symbolicBitVector<isSigned>& op) const
480
{
481
  return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
482
6
      (isSigned) ? kind::BITVECTOR_SDIV : kind::BITVECTOR_UDIV, *this, op));
483
}
484
485
template <bool isSigned>
486
6
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator%(
487
    const symbolicBitVector<isSigned>& op) const
488
{
489
  return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
490
6
      (isSigned) ? kind::BITVECTOR_SREM : kind::BITVECTOR_UREM, *this, op));
491
}
492
493
template <bool isSigned>
494
29628
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator-(void) const
495
{
496
  return symbolicBitVector<isSigned>(
497
29628
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_NEG, *this));
498
}
499
500
template <bool isSigned>
501
3730
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator~(void) const
502
{
503
  return symbolicBitVector<isSigned>(
504
3730
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, *this));
505
}
506
507
template <bool isSigned>
508
5
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::increment() const
509
{
510
  return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
511
5
      kind::BITVECTOR_ADD, *this, one(this->getWidth())));
512
}
513
514
template <bool isSigned>
515
3907
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::decrement() const
516
{
517
  return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
518
3907
      kind::BITVECTOR_SUB, *this, one(this->getWidth())));
519
}
520
521
template <bool isSigned>
522
183
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::signExtendRightShift(
523
    const symbolicBitVector<isSigned>& op) const
524
{
525
  return symbolicBitVector<isSigned>(
526
183
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_ASHR, *this, op));
527
}
528
529
/*** Modular operations ***/
530
// No overflow checking so these are the same as other operations
531
template <bool isSigned>
532
4146
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularLeftShift(
533
    const symbolicBitVector<isSigned>& op) const
534
{
535
4146
  return *this << op;
536
}
537
538
template <bool isSigned>
539
25
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularRightShift(
540
    const symbolicBitVector<isSigned>& op) const
541
{
542
25
  return *this >> op;
543
}
544
545
template <bool isSigned>
546
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularIncrement()
547
    const
548
{
549
  return this->increment();
550
}
551
552
template <bool isSigned>
553
3814
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularDecrement()
554
    const
555
{
556
3814
  return this->decrement();
557
}
558
559
template <bool isSigned>
560
684
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularAdd(
561
    const symbolicBitVector<isSigned>& op) const
562
{
563
684
  return *this + op;
564
}
565
566
template <bool isSigned>
567
672
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularNegate() const
568
{
569
672
  return -(*this);
570
}
571
572
/*** Comparisons ***/
573
574
template <bool isSigned>
575
135508
symbolicProposition symbolicBitVector<isSigned>::operator==(
576
    const symbolicBitVector<isSigned>& op) const
577
{
578
  return symbolicProposition(
579
135508
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_COMP, *this, op));
580
}
581
582
template <bool isSigned>
583
42012
symbolicProposition symbolicBitVector<isSigned>::operator<=(
584
    const symbolicBitVector<isSigned>& op) const
585
{
586
  // Consider adding kind::BITVECTOR_SLEBV and BITVECTOR_ULEBV
587
42012
  return (*this < op) || (*this == op);
588
}
589
590
template <bool isSigned>
591
4717
symbolicProposition symbolicBitVector<isSigned>::operator>=(
592
    const symbolicBitVector<isSigned>& op) const
593
{
594
4717
  return (*this > op) || (*this == op);
595
}
596
597
template <bool isSigned>
598
42658
symbolicProposition symbolicBitVector<isSigned>::operator<(
599
    const symbolicBitVector<isSigned>& op) const
600
{
601
  return symbolicProposition(NodeManager::currentNM()->mkNode(
602
42658
      (isSigned) ? kind::BITVECTOR_SLTBV : kind::BITVECTOR_ULTBV, *this, op));
603
}
604
605
template <bool isSigned>
606
5708
symbolicProposition symbolicBitVector<isSigned>::operator>(
607
    const symbolicBitVector<isSigned>& op) const
608
{
609
  return symbolicProposition(NodeManager::currentNM()->mkNode(
610
5708
      (isSigned) ? kind::BITVECTOR_SLTBV : kind::BITVECTOR_ULTBV, op, *this));
611
}
612
613
/*** Type conversion ***/
614
// cvc5 nodes make no distinction between signed and unsigned, thus ...
615
template <bool isSigned>
616
68
symbolicBitVector<true> symbolicBitVector<isSigned>::toSigned(void) const
617
{
618
68
  return symbolicBitVector<true>(*this);
619
}
620
template <bool isSigned>
621
7791
symbolicBitVector<false> symbolicBitVector<isSigned>::toUnsigned(void) const
622
{
623
7791
  return symbolicBitVector<false>(*this);
624
}
625
626
/*** Bit hacks ***/
627
template <>
628
732
symbolicBitVector<true> symbolicBitVector<true>::extend(bwt extension) const
629
{
630
1464
  NodeBuilder construct(kind::BITVECTOR_SIGN_EXTEND);
631
2196
  construct << NodeManager::currentNM()->mkConst<BitVectorSignExtend>(
632
2928
      BitVectorSignExtend(extension))
633
732
            << *this;
634
635
1464
  return symbolicBitVector<true>(construct);
636
}
637
638
template <>
639
10037
symbolicBitVector<false> symbolicBitVector<false>::extend(bwt extension) const
640
{
641
20074
  NodeBuilder construct(kind::BITVECTOR_ZERO_EXTEND);
642
30111
  construct << NodeManager::currentNM()->mkConst<BitVectorZeroExtend>(
643
40148
      BitVectorZeroExtend(extension))
644
10037
            << *this;
645
646
20074
  return symbolicBitVector<false>(construct);
647
}
648
649
template <bool isSigned>
650
70
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::contract(
651
    bwt reduction) const
652
{
653
70
  Assert(this->getWidth() > reduction);
654
655
140
  NodeBuilder construct(kind::BITVECTOR_EXTRACT);
656
280
  construct << NodeManager::currentNM()->mkConst<BitVectorExtract>(
657
70
      BitVectorExtract((this->getWidth() - 1) - reduction, 0))
658
140
            << *this;
659
660
140
  return symbolicBitVector<isSigned>(construct);
661
}
662
663
template <bool isSigned>
664
3892
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::resize(
665
    bwt newSize) const
666
{
667
3892
  bwt width = this->getWidth();
668
669
3892
  if (newSize > width)
670
  {
671
3891
    return this->extend(newSize - width);
672
  }
673
1
  else if (newSize < width)
674
  {
675
1
    return this->contract(width - newSize);
676
  }
677
  else
678
  {
679
    return *this;
680
  }
681
}
682
683
template <bool isSigned>
684
6045
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::matchWidth(
685
    const symbolicBitVector<isSigned>& op) const
686
{
687
6045
  Assert(this->getWidth() <= op.getWidth());
688
6045
  return this->extend(op.getWidth() - this->getWidth());
689
}
690
691
template <bool isSigned>
692
71270
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::append(
693
    const symbolicBitVector<isSigned>& op) const
694
{
695
  return symbolicBitVector<isSigned>(
696
71270
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_CONCAT, *this, op));
697
}
698
699
// Inclusive of end points, thus if the same, extracts just one bit
700
template <bool isSigned>
701
148861
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::extract(
702
    bwt upper, bwt lower) const
703
{
704
148861
  Assert(upper >= lower);
705
706
297722
  NodeBuilder construct(kind::BITVECTOR_EXTRACT);
707
446583
  construct << NodeManager::currentNM()->mkConst<BitVectorExtract>(
708
      BitVectorExtract(upper, lower))
709
297722
            << *this;
710
711
297722
  return symbolicBitVector<isSigned>(construct);
712
}
713
714
2655
floatingPointTypeInfo::floatingPointTypeInfo(const TypeNode type)
715
2655
    : FloatingPointSize(type.getConst<FloatingPointSize>())
716
{
717
2655
  Assert(type.isFloatingPoint());
718
2655
}
719
46
floatingPointTypeInfo::floatingPointTypeInfo(unsigned exp, unsigned sig)
720
46
    : FloatingPointSize(exp, sig)
721
{
722
46
}
723
floatingPointTypeInfo::floatingPointTypeInfo(const floatingPointTypeInfo& old)
724
    : FloatingPointSize(old)
725
{
726
}
727
728
1973
TypeNode floatingPointTypeInfo::getTypeNode(void) const
729
{
730
1973
  return NodeManager::currentNM()->mkFloatingPointType(*this);
731
}
732
}  // namespace symfpuSymbolic
733
734
6271
FpWordBlaster::FpWordBlaster(context::UserContext* user)
735
    : d_additionalAssertions(user),
736
      d_fpMap(user),
737
      d_rmMap(user),
738
      d_boolMap(user),
739
      d_ubvMap(user),
740
6271
      d_sbvMap(user)
741
{
742
6271
}
743
744
6268
FpWordBlaster::~FpWordBlaster() {}
745
746
1973
Node FpWordBlaster::ufToNode(const fpt& format, const uf& u) const
747
{
748
1973
  NodeManager* nm = NodeManager::currentNM();
749
750
1973
  FloatingPointSize fps(format.getTypeNode().getConst<FloatingPointSize>());
751
752
  // This is not entirely obvious but it builds a float from components
753
  // Particularly, if the components can be constant folded, it should
754
  // build a Node containing a constant FloatingPoint number
755
756
3946
  ubv packed(symfpu::pack<traits>(format, u));
757
  Node value =
758
1973
      nm->mkNode(nm->mkConst(FloatingPointToFPIEEEBitVector(fps)), packed);
759
3946
  return value;
760
}
761
762
76
Node FpWordBlaster::rmToNode(const rm& r) const
763
{
764
76
  NodeManager* nm = NodeManager::currentNM();
765
766
152
  Node transVar = r;
767
768
152
  Node RNE = traits::RNE();
769
152
  Node RNA = traits::RNA();
770
152
  Node RTP = traits::RTP();
771
152
  Node RTN = traits::RTN();
772
152
  Node RTZ = traits::RTZ();
773
774
  Node value = nm->mkNode(
775
      kind::ITE,
776
152
      nm->mkNode(kind::EQUAL, transVar, RNE),
777
152
      nm->mkConst(RoundingMode::ROUND_NEAREST_TIES_TO_EVEN),
778
456
      nm->mkNode(
779
          kind::ITE,
780
152
          nm->mkNode(kind::EQUAL, transVar, RNA),
781
152
          nm->mkConst(RoundingMode::ROUND_NEAREST_TIES_TO_AWAY),
782
456
          nm->mkNode(
783
              kind::ITE,
784
152
              nm->mkNode(kind::EQUAL, transVar, RTP),
785
152
              nm->mkConst(RoundingMode::ROUND_TOWARD_POSITIVE),
786
456
              nm->mkNode(kind::ITE,
787
152
                         nm->mkNode(kind::EQUAL, transVar, RTN),
788
152
                         nm->mkConst(RoundingMode::ROUND_TOWARD_NEGATIVE),
789
532
                         nm->mkConst(RoundingMode::ROUND_TOWARD_ZERO)))));
790
152
  return value;
791
}
792
793
Node FpWordBlaster::propToNode(const prop& p) const
794
{
795
  NodeManager* nm = NodeManager::currentNM();
796
  Node value =
797
      nm->mkNode(kind::EQUAL, p, nm->mkConst(::cvc5::BitVector(1U, 1U)));
798
  return value;
799
}
800
Node FpWordBlaster::ubvToNode(const ubv& u) const { return u; }
801
Node FpWordBlaster::sbvToNode(const sbv& s) const { return s; }
802
// Creates the components constraint
803
104
FpWordBlaster::uf FpWordBlaster::buildComponents(TNode current)
804
{
805
104
  Assert(Theory::isLeafOf(current, THEORY_FP)
806
         || current.getKind() == kind::FLOATINGPOINT_TO_FP_REAL);
807
808
104
  NodeManager* nm = NodeManager::currentNM();
809
208
  uf tmp(nm->mkNode(kind::FLOATINGPOINT_COMPONENT_NAN, current),
810
208
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_INF, current),
811
208
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_ZERO, current),
812
208
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_SIGN, current),
813
208
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_EXPONENT, current),
814
1144
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_SIGNIFICAND, current));
815
816
104
  d_additionalAssertions.push_back(tmp.valid(fpt(current.getType())));
817
818
104
  return tmp;
819
}
820
821
1885
Node FpWordBlaster::wordBlast(TNode node)
822
{
823
3770
  std::vector<TNode> visit;
824
3770
  std::unordered_map<TNode, bool> visited;
825
1885
  NodeManager* nm = NodeManager::currentNM();
826
827
1885
  visit.push_back(node);
828
829
16389
  while (!visit.empty())
830
  {
831
12238
    TNode cur = visit.back();
832
7252
    visit.pop_back();
833
12238
    TypeNode t(cur.getType());
834
835
    /* Already word-blasted, skip. */
836
16080
    if ((t.isBoolean() && d_boolMap.find(cur) != d_boolMap.end())
837
14504
        || (t.isRoundingMode() && d_rmMap.find(cur) != d_rmMap.end())
838
7183
        || (t.isBitVector()
839
9606
            && (d_sbvMap.find(cur) != d_sbvMap.end()
840
9606
                || d_ubvMap.find(cur) != d_ubvMap.end()))
841
21687
        || (t.isFloatingPoint() && d_fpMap.find(cur) != d_fpMap.end()))
842
    {
843
2144
      continue;
844
    }
845
846
5108
    Kind kind = cur.getKind();
847
848
5108
    if (t.isReal() && kind != kind::FLOATINGPOINT_TO_REAL_TOTAL)
849
    {
850
      // The only nodes with Real sort in Theory FP are of kind
851
      // kind::FLOATINGPOINT_TO_REAL_TOTAL (kind::FLOATINGPOINT_TO_REAL is
852
      // rewritten to kind::FLOATINGPOINT_TO_REAL_TOTAL).
853
      // We don't need to do anything explicitly with them since they will be
854
      // treated as an uninterpreted function by the Real theory and we don't
855
      // need to bit-blast the float expression unless we need to say something
856
      // about its value.
857
      //
858
      // We still have to word blast it's arguments, though.
859
      //
860
      // All other Real expressions can be skipped.
861
122
      continue;
862
    }
863
864
4986
    auto it = visited.find(cur);
865
4986
    if (it == visited.end())
866
    {
867
2493
      visited.emplace(cur, 0);
868
2493
      visit.push_back(cur);
869
2493
      visit.insert(visit.end(), cur.begin(), cur.end());
870
    }
871
2493
    else if (it->second == false)
872
    {
873
2493
      it->second = true;
874
875
2493
      if (t.isRoundingMode())
876
      {
877
        /* ---- RoundingMode constants and variables -------------- */
878
31
        Assert(Theory::isLeafOf(cur, THEORY_FP));
879
31
        if (kind == kind::CONST_ROUNDINGMODE)
880
        {
881
13
          switch (cur.getConst<RoundingMode>())
882
          {
883
10
            case RoundingMode::ROUND_NEAREST_TIES_TO_EVEN:
884
10
              d_rmMap.insert(cur, traits::RNE());
885
10
              break;
886
1
            case RoundingMode::ROUND_NEAREST_TIES_TO_AWAY:
887
1
              d_rmMap.insert(cur, traits::RNA());
888
1
              break;
889
1
            case RoundingMode::ROUND_TOWARD_POSITIVE:
890
1
              d_rmMap.insert(cur, traits::RTP());
891
1
              break;
892
            case RoundingMode::ROUND_TOWARD_NEGATIVE:
893
              d_rmMap.insert(cur, traits::RTN());
894
              break;
895
1
            case RoundingMode::ROUND_TOWARD_ZERO:
896
1
              d_rmMap.insert(cur, traits::RTZ());
897
1
              break;
898
            default: Unreachable() << "Unknown rounding mode"; break;
899
          }
900
        }
901
        else
902
        {
903
36
          rm tmp(nm->mkNode(kind::ROUNDINGMODE_BITBLAST, cur));
904
18
          d_rmMap.insert(cur, tmp);
905
18
          d_additionalAssertions.push_back(tmp.valid());
906
        }
907
      }
908
2462
      else if (t.isFloatingPoint())
909
      {
910
        /* ---- FloatingPoint constants and variables ------------- */
911
396
        if (Theory::isLeafOf(cur, THEORY_FP))
912
        {
913
307
          if (kind == kind::CONST_FLOATINGPOINT)
914
          {
915
416
            d_fpMap.insert(
916
                cur,
917
416
                symfpu::unpackedFloat<traits>(
918
208
                    cur.getConst<FloatingPoint>().getLiteral()->getSymUF()));
919
          }
920
          else
921
          {
922
99
            d_fpMap.insert(cur, buildComponents(cur));
923
          }
924
        }
925
        else
926
        {
927
          /* ---- FloatingPoint operators --------------------------- */
928
89
          Assert(kind != kind::CONST_FLOATINGPOINT);
929
89
          Assert(kind != kind::VARIABLE);
930
89
          Assert(kind != kind::BOUND_VARIABLE && kind != kind::SKOLEM);
931
932
89
          switch (kind)
933
          {
934
            /* ---- Arithmetic operators ---- */
935
9
            case kind::FLOATINGPOINT_ABS:
936
9
              Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
937
18
              d_fpMap.insert(cur,
938
27
                             symfpu::absolute<traits>(
939
27
                                 fpt(t), (*d_fpMap.find(cur[0])).second));
940
9
              break;
941
942
7
            case kind::FLOATINGPOINT_NEG:
943
7
              Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
944
14
              d_fpMap.insert(cur,
945
21
                             symfpu::negate<traits>(
946
21
                                 fpt(t), (*d_fpMap.find(cur[0])).second));
947
7
              break;
948
949
1
            case kind::FLOATINGPOINT_SQRT:
950
1
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
951
1
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
952
2
              d_fpMap.insert(
953
                  cur,
954
3
                  symfpu::sqrt<traits>(fpt(t),
955
2
                                       (*d_rmMap.find(cur[0])).second,
956
2
                                       (*d_fpMap.find(cur[1])).second));
957
1
              break;
958
959
5
            case kind::FLOATINGPOINT_RTI:
960
5
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
961
5
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
962
10
              d_fpMap.insert(cur,
963
20
                             symfpu::roundToIntegral<traits>(
964
10
                                 fpt(t),
965
10
                                 (*d_rmMap.find(cur[0])).second,
966
10
                                 (*d_fpMap.find(cur[1])).second));
967
5
              break;
968
969
10
            case kind::FLOATINGPOINT_REM:
970
10
              Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
971
10
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
972
20
              d_fpMap.insert(
973
                  cur,
974
30
                  symfpu::remainder<traits>(fpt(t),
975
20
                                            (*d_fpMap.find(cur[0])).second,
976
20
                                            (*d_fpMap.find(cur[1])).second));
977
10
              break;
978
979
            case kind::FLOATINGPOINT_MAX_TOTAL:
980
              Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
981
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
982
              Assert(cur[2].getType().isBitVector());
983
              d_fpMap.insert(cur,
984
                             symfpu::max<traits>(fpt(t),
985
                                                 (*d_fpMap.find(cur[0])).second,
986
                                                 (*d_fpMap.find(cur[1])).second,
987
                                                 prop(cur[2])));
988
              break;
989
990
            case kind::FLOATINGPOINT_MIN_TOTAL:
991
              Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
992
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
993
              Assert(cur[2].getType().isBitVector());
994
              d_fpMap.insert(cur,
995
                             symfpu::min<traits>(fpt(t),
996
                                                 (*d_fpMap.find(cur[0])).second,
997
                                                 (*d_fpMap.find(cur[1])).second,
998
                                                 prop(cur[2])));
999
              break;
1000
1001
15
            case kind::FLOATINGPOINT_ADD:
1002
15
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1003
15
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1004
15
              Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
1005
30
              d_fpMap.insert(cur,
1006
60
                             symfpu::add<traits>(fpt(t),
1007
30
                                                 (*d_rmMap.find(cur[0])).second,
1008
30
                                                 (*d_fpMap.find(cur[1])).second,
1009
30
                                                 (*d_fpMap.find(cur[2])).second,
1010
30
                                                 prop(true)));
1011
15
              break;
1012
1013
12
            case kind::FLOATINGPOINT_MULT:
1014
12
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1015
12
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1016
12
              Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
1017
24
              d_fpMap.insert(
1018
                  cur,
1019
48
                  symfpu::multiply<traits>(fpt(t),
1020
24
                                           (*d_rmMap.find(cur[0])).second,
1021
24
                                           (*d_fpMap.find(cur[1])).second,
1022
24
                                           (*d_fpMap.find(cur[2])).second));
1023
12
              break;
1024
1025
6
            case kind::FLOATINGPOINT_DIV:
1026
6
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1027
6
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1028
6
              Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
1029
12
              d_fpMap.insert(
1030
                  cur,
1031
24
                  symfpu::divide<traits>(fpt(t),
1032
12
                                         (*d_rmMap.find(cur[0])).second,
1033
12
                                         (*d_fpMap.find(cur[1])).second,
1034
12
                                         (*d_fpMap.find(cur[2])).second));
1035
6
              break;
1036
1037
            case kind::FLOATINGPOINT_FMA:
1038
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1039
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1040
              Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
1041
              Assert(d_fpMap.find(cur[3]) != d_fpMap.end());
1042
1043
              d_fpMap.insert(
1044
                  cur,
1045
                  symfpu::fma<traits>(fpt(t),
1046
                                      (*d_rmMap.find(cur[0])).second,
1047
                                      (*d_fpMap.find(cur[1])).second,
1048
                                      (*d_fpMap.find(cur[2])).second,
1049
                                      (*d_fpMap.find(cur[3])).second));
1050
              break;
1051
1052
            /* ---- Conversions ---- */
1053
2
            case kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT:
1054
2
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1055
2
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1056
4
              d_fpMap.insert(cur,
1057
8
                             symfpu::convertFloatToFloat<traits>(
1058
4
                                 fpt(cur[1].getType()),
1059
4
                                 fpt(t),
1060
4
                                 (*d_rmMap.find(cur[0])).second,
1061
4
                                 (*d_fpMap.find(cur[1])).second));
1062
2
              break;
1063
1064
2
            case kind::FLOATINGPOINT_FP:
1065
            {
1066
2
              Assert(cur[0].getType().isBitVector());
1067
2
              Assert(cur[1].getType().isBitVector());
1068
2
              Assert(cur[2].getType().isBitVector());
1069
1070
              Node IEEEBV(
1071
4
                  nm->mkNode(kind::BITVECTOR_CONCAT, cur[0], cur[1], cur[2]));
1072
4
              d_fpMap.insert(cur, symfpu::unpack<traits>(fpt(t), IEEEBV));
1073
            }
1074
2
            break;
1075
1076
13
            case kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR:
1077
13
              Assert(cur[0].getType().isBitVector());
1078
13
              d_fpMap.insert(cur, symfpu::unpack<traits>(fpt(t), ubv(cur[0])));
1079
13
              break;
1080
1081
            case kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR:
1082
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1083
              d_fpMap.insert(
1084
                  cur,
1085
                  symfpu::convertSBVToFloat<traits>(
1086
                      fpt(t), (*d_rmMap.find(cur[0])).second, sbv(cur[1])));
1087
              break;
1088
1089
2
            case kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR:
1090
2
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1091
4
              d_fpMap.insert(
1092
                  cur,
1093
10
                  symfpu::convertUBVToFloat<traits>(
1094
6
                      fpt(t), (*d_rmMap.find(cur[0])).second, ubv(cur[1])));
1095
2
              break;
1096
1097
5
            case kind::FLOATINGPOINT_TO_FP_REAL:
1098
5
              d_fpMap.insert(cur, buildComponents(cur));
1099
              // Rely on the real theory and theory combination
1100
              // to handle the value
1101
5
              break;
1102
1103
            default: Unreachable() << "Unhandled kind " << kind; break;
1104
          }
1105
        }
1106
      }
1107
2066
      else if (t.isBoolean())
1108
      {
1109
788
        switch (kind)
1110
        {
1111
          /* ---- Comparisons --------------------------------------- */
1112
543
          case kind::EQUAL:
1113
          {
1114
1086
            TypeNode childType(cur[0].getType());
1115
1116
543
            if (childType.isFloatingPoint())
1117
            {
1118
246
              Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1119
246
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1120
492
              d_boolMap.insert(
1121
                  cur,
1122
738
                  symfpu::smtlibEqual<traits>(fpt(childType),
1123
492
                                              (*d_fpMap.find(cur[0])).second,
1124
492
                                              (*d_fpMap.find(cur[1])).second));
1125
            }
1126
297
            else if (childType.isRoundingMode())
1127
            {
1128
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1129
              Assert(d_rmMap.find(cur[1]) != d_rmMap.end());
1130
              d_boolMap.insert(cur,
1131
                               (*d_rmMap.find(cur[0])).second
1132
                                   == (*d_rmMap.find(cur[1])).second);
1133
543
            }
1134
            // else do nothing
1135
          }
1136
543
          break;
1137
1138
146
          case kind::FLOATINGPOINT_LEQ:
1139
146
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1140
146
            Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1141
292
            d_boolMap.insert(cur,
1142
584
                             symfpu::lessThanOrEqual<traits>(
1143
292
                                 fpt(cur[0].getType()),
1144
292
                                 (*d_fpMap.find(cur[0])).second,
1145
292
                                 (*d_fpMap.find(cur[1])).second));
1146
146
            break;
1147
1148
4
          case kind::FLOATINGPOINT_LT:
1149
4
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1150
4
            Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1151
8
            d_boolMap.insert(
1152
                cur,
1153
12
                symfpu::lessThan<traits>(fpt(cur[0].getType()),
1154
8
                                         (*d_fpMap.find(cur[0])).second,
1155
8
                                         (*d_fpMap.find(cur[1])).second));
1156
4
            break;
1157
1158
          /* ---- Tester -------------------------------------------- */
1159
1
          case kind::FLOATINGPOINT_ISN:
1160
1
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1161
2
            d_boolMap.insert(
1162
                cur,
1163
2
                symfpu::isNormal<traits>(fpt(cur[0].getType()),
1164
2
                                         (*d_fpMap.find(cur[0])).second));
1165
1
            break;
1166
1167
3
          case kind::FLOATINGPOINT_ISSN:
1168
3
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1169
6
            d_boolMap.insert(
1170
                cur,
1171
6
                symfpu::isSubnormal<traits>(fpt(cur[0].getType()),
1172
6
                                            (*d_fpMap.find(cur[0])).second));
1173
3
            break;
1174
1175
9
          case kind::FLOATINGPOINT_ISZ:
1176
9
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1177
18
            d_boolMap.insert(
1178
                cur,
1179
18
                symfpu::isZero<traits>(fpt(cur[0].getType()),
1180
18
                                       (*d_fpMap.find(cur[0])).second));
1181
9
            break;
1182
1183
33
          case kind::FLOATINGPOINT_ISINF:
1184
33
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1185
66
            d_boolMap.insert(
1186
                cur,
1187
66
                symfpu::isInfinite<traits>(fpt(cur[0].getType()),
1188
66
                                           (*d_fpMap.find(cur[0])).second));
1189
33
            break;
1190
1191
27
          case kind::FLOATINGPOINT_ISNAN:
1192
27
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1193
54
            d_boolMap.insert(
1194
                cur,
1195
54
                symfpu::isNaN<traits>(fpt(cur[0].getType()),
1196
54
                                      (*d_fpMap.find(cur[0])).second));
1197
27
            break;
1198
1199
20
          case kind::FLOATINGPOINT_ISNEG:
1200
20
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1201
40
            d_boolMap.insert(
1202
                cur,
1203
40
                symfpu::isNegative<traits>(fpt(cur[0].getType()),
1204
40
                                           (*d_fpMap.find(cur[0])).second));
1205
20
            break;
1206
1207
2
          case kind::FLOATINGPOINT_ISPOS:
1208
2
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1209
4
            d_boolMap.insert(
1210
                cur,
1211
4
                symfpu::isPositive<traits>(fpt(cur[0].getType()),
1212
4
                                           (*d_fpMap.find(cur[0])).second));
1213
2
            break;
1214
1215
788
          default:;  // do nothing
1216
        }
1217
      }
1218
1278
      else if (t.isBitVector())
1219
      {
1220
        /* ---- Conversions --------------------------------------- */
1221
1177
        if (kind == kind::FLOATINGPOINT_TO_UBV_TOTAL)
1222
        {
1223
          Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1224
          Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1225
          FloatingPointToUBVTotal info =
1226
              cur.getOperator().getConst<FloatingPointToUBVTotal>();
1227
          d_ubvMap.insert(
1228
              cur,
1229
              symfpu::convertFloatToUBV<traits>(fpt(cur[1].getType()),
1230
                                                (*d_rmMap.find(cur[0])).second,
1231
                                                (*d_fpMap.find(cur[1])).second,
1232
                                                info.d_bv_size,
1233
                                                ubv(cur[2])));
1234
        }
1235
1177
        else if (kind == kind::FLOATINGPOINT_TO_SBV_TOTAL)
1236
        {
1237
1
          Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1238
1
          Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1239
          FloatingPointToSBVTotal info =
1240
1
              cur.getOperator().getConst<FloatingPointToSBVTotal>();
1241
1242
2
          d_sbvMap.insert(
1243
              cur,
1244
5
              symfpu::convertFloatToSBV<traits>(fpt(cur[1].getType()),
1245
2
                                                (*d_rmMap.find(cur[0])).second,
1246
2
                                                (*d_fpMap.find(cur[1])).second,
1247
                                                info.d_bv_size,
1248
2
                                                sbv(cur[2])));
1249
        }
1250
        // else do nothing
1251
      }
1252
    }
1253
    else
1254
    {
1255
      Assert(visited.at(cur) == 1);
1256
      continue;
1257
    }
1258
  }
1259
1260
1885
  if (d_boolMap.find(node) != d_boolMap.end())
1261
  {
1262
491
    Assert(node.getType().isBoolean());
1263
491
    return (*d_boolMap.find(node)).second;
1264
  }
1265
1394
  if (d_sbvMap.find(node) != d_sbvMap.end())
1266
  {
1267
1
    Assert(node.getKind() == kind::FLOATINGPOINT_TO_SBV_TOTAL);
1268
1
    return (*d_sbvMap.find(node)).second;
1269
  }
1270
1393
  if (d_ubvMap.find(node) != d_ubvMap.end())
1271
  {
1272
    Assert(node.getKind() == kind::FLOATINGPOINT_TO_UBV_TOTAL);
1273
    return (*d_ubvMap.find(node)).second;
1274
  }
1275
1393
  return node;
1276
}
1277
1278
2049
Node FpWordBlaster::getValue(Valuation& val, TNode var)
1279
{
1280
2049
  Assert(Theory::isLeafOf(var, THEORY_FP));
1281
1282
4098
  TypeNode t(var.getType());
1283
1284
2049
  Assert(t.isRoundingMode() || t.isFloatingPoint())
1285
      << "Asking for the value of a type that is not managed by the "
1286
         "floating-point theory";
1287
1288
2049
  if (t.isRoundingMode())
1289
  {
1290
76
    rmMap::const_iterator i(d_rmMap.find(var));
1291
76
    if (i == d_rmMap.end())
1292
    {
1293
      return Node::null();
1294
    }
1295
76
    return rmToNode((*i).second);
1296
  }
1297
1298
1973
  fpMap::const_iterator i(d_fpMap.find(var));
1299
1973
  if (i == d_fpMap.end())
1300
  {
1301
    return Node::null();
1302
  }
1303
1973
  return ufToNode(fpt(t), (*i).second);
1304
}
1305
1306
}  // namespace fp
1307
}  // namespace theory
1308
22746
}  // namespace cvc5