GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/fp/fp_word_blaster.cpp Lines: 517 596 86.7 %
Date: 2021-09-18 Branches: 1386 4249 32.6 %

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
4406
CVC5_SYM_ITE_DFN(traits::prop);
116
9274
CVC5_SYM_ITE_DFN(traits::sbv);
117
18843
CVC5_SYM_ITE_DFN(traits::ubv);
118
119
#undef CVC5_SYM_ITE_DFN
120
121
template <>
122
5015
traits::ubv orderEncode<traits, traits::ubv>(const traits::ubv& b)
123
{
124
5015
  return orderEncodeBitwise<traits, traits::ubv>(b);
125
}
126
127
template <>
128
35
stickyRightShiftResult<traits> stickyRightShift(const traits::ubv& input,
129
                                                const traits::ubv& shiftAmount)
130
{
131
35
  return stickyRightShiftBitwise<traits>(input, shiftAmount);
132
}
133
134
template <>
135
8523
void probabilityAnnotation<traits, traits::prop>(const traits::prop& p,
136
                                                 const probability& pr)
137
{
138
  // For now, do nothing...
139
8523
  return;
140
}
141
};  // namespace symfpu
142
143
namespace cvc5 {
144
namespace theory {
145
namespace fp {
146
namespace symfpuSymbolic {
147
148
378
symbolicRoundingMode traits::RNE(void) { return symbolicRoundingMode(0x01); };
149
356
symbolicRoundingMode traits::RNA(void) { return symbolicRoundingMode(0x02); };
150
357
symbolicRoundingMode traits::RTP(void) { return symbolicRoundingMode(0x04); };
151
424
symbolicRoundingMode traits::RTN(void) { return symbolicRoundingMode(0x08); };
152
301
symbolicRoundingMode traits::RTZ(void) { return symbolicRoundingMode(0x10); };
153
154
6662
void traits::precondition(const bool b)
155
{
156
6662
  Assert(b);
157
6662
  return;
158
}
159
3215
void traits::postcondition(const bool b)
160
{
161
3215
  Assert(b);
162
3215
  return;
163
}
164
64046
void traits::invariant(const bool b)
165
{
166
64046
  Assert(b);
167
64046
  return;
168
}
169
170
5405
void traits::precondition(const prop& p) { return; }
171
5596
void traits::postcondition(const prop& p) { return; }
172
16648
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
542461
bool symbolicProposition::checkNodeType(const TNode node)
178
{
179
1084922
  TypeNode tn = node.getType(false);
180
1084922
  return tn.isBitVector() && tn.getBitVectorSize() == 1;
181
}
182
183
509685
symbolicProposition::symbolicProposition(const Node n) : nodeWrapper(n)
184
{
185
509685
  Assert(checkNodeType(*this));
186
509685
}  // Only used within this header so could be friend'd
187
20829
symbolicProposition::symbolicProposition(bool v)
188
    : nodeWrapper(
189
20829
        NodeManager::currentNM()->mkConst(BitVector(1U, (v ? 1U : 0U))))
190
{
191
20829
  Assert(checkNodeType(*this));
192
20829
}
193
194
11947
symbolicProposition::symbolicProposition(const symbolicProposition& old)
195
11947
    : nodeWrapper(old)
196
{
197
11947
  Assert(checkNodeType(*this));
198
11947
}
199
200
60053
symbolicProposition symbolicProposition::operator!(void) const
201
{
202
  return symbolicProposition(
203
60053
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, *this));
204
}
205
206
81518
symbolicProposition symbolicProposition::operator&&(
207
    const symbolicProposition& op) const
208
{
209
  return symbolicProposition(
210
81518
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_AND, *this, op));
211
}
212
213
132820
symbolicProposition symbolicProposition::operator||(
214
    const symbolicProposition& op) const
215
{
216
  return symbolicProposition(
217
132820
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_OR, *this, op));
218
}
219
220
9708
symbolicProposition symbolicProposition::operator==(
221
    const symbolicProposition& op) const
222
{
223
  return symbolicProposition(
224
9708
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_COMP, *this, op));
225
}
226
227
229
symbolicProposition symbolicProposition::operator^(
228
    const symbolicProposition& op) const
229
{
230
  return symbolicProposition(
231
229
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_XOR, *this, op));
232
}
233
234
1935
bool symbolicRoundingMode::checkNodeType(const TNode n)
235
{
236
1935
  return n.getType(false).isBitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES);
237
}
238
239
21
symbolicRoundingMode::symbolicRoundingMode(const Node n) : nodeWrapper(n)
240
{
241
21
  Assert(checkNodeType(*this));
242
21
}
243
244
1816
symbolicRoundingMode::symbolicRoundingMode(const unsigned v)
245
5448
    : nodeWrapper(NodeManager::currentNM()->mkConst(
246
7264
        BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, v)))
247
{
248
1816
  Assert((v & (v - 1)) == 0 && v != 0);  // Exactly one bit set
249
1816
  Assert(checkNodeType(*this));
250
1816
}
251
252
98
symbolicRoundingMode::symbolicRoundingMode(const symbolicRoundingMode& old)
253
98
    : nodeWrapper(old)
254
{
255
98
  Assert(checkNodeType(*this));
256
98
}
257
258
21
symbolicProposition symbolicRoundingMode::valid(void) const
259
{
260
21
  NodeManager* nm = NodeManager::currentNM();
261
42
  Node zero(nm->mkConst(BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, 0u)));
262
263
  // Is there a better encoding of this?
264
84
  return symbolicProposition(nm->mkNode(
265
      kind::BITVECTOR_AND,
266
84
      nm->mkNode(
267
          kind::BITVECTOR_COMP,
268
42
          nm->mkNode(kind::BITVECTOR_AND,
269
                     *this,
270
42
                     nm->mkNode(kind::BITVECTOR_SUB,
271
                                *this,
272
42
                                nm->mkConst(BitVector(
273
                                    SYMFPU_NUMBER_OF_ROUNDING_MODES, 1u)))),
274
          zero),
275
42
      nm->mkNode(kind::BITVECTOR_NOT,
276
84
                 nm->mkNode(kind::BITVECTOR_COMP, *this, zero))));
277
}
278
279
1012
symbolicProposition symbolicRoundingMode::operator==(
280
    const symbolicRoundingMode& op) const
281
{
282
  return symbolicProposition(
283
1012
      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
69374
Node symbolicBitVector<isSigned>::fromProposition(Node node) const
308
{
309
69374
  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
562046
symbolicBitVector<isSigned>::symbolicBitVector(const Node n) : nodeWrapper(n)
319
{
320
562046
  Assert(checkNodeType(*this));
321
562046
}
322
323
template <bool isSigned>
324
869014
bool symbolicBitVector<isSigned>::checkNodeType(const TNode n)
325
{
326
869014
  return n.getType(false).isBitVector();
327
}
328
329
template <bool isSigned>
330
290082
symbolicBitVector<isSigned>::symbolicBitVector(const bwt w, const unsigned v)
331
290082
    : nodeWrapper(NodeManager::currentNM()->mkConst(BitVector(w, v)))
332
{
333
290082
  Assert(checkNodeType(*this));
334
290082
}
335
template <bool isSigned>
336
69374
symbolicBitVector<isSigned>::symbolicBitVector(const symbolicProposition& p)
337
69374
    : nodeWrapper(fromProposition(p))
338
{
339
69374
}
340
template <bool isSigned>
341
16368
symbolicBitVector<isSigned>::symbolicBitVector(
342
    const symbolicBitVector<isSigned>& old)
343
16368
    : nodeWrapper(old)
344
{
345
16368
  Assert(checkNodeType(*this));
346
16368
}
347
template <bool isSigned>
348
518
symbolicBitVector<isSigned>::symbolicBitVector(const BitVector& old)
349
518
    : nodeWrapper(NodeManager::currentNM()->mkConst(old))
350
{
351
518
  Assert(checkNodeType(*this));
352
518
}
353
354
template <bool isSigned>
355
93021
bwt symbolicBitVector<isSigned>::getWidth(void) const
356
{
357
93021
  return this->getType(false).getBitVectorSize();
358
}
359
360
/*** Constant creation and test ***/
361
template <bool isSigned>
362
96713
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::one(const bwt& w)
363
{
364
96713
  return symbolicBitVector<isSigned>(w, 1);
365
}
366
template <bool isSigned>
367
42262
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::zero(const bwt& w)
368
{
369
42262
  return symbolicBitVector<isSigned>(w, 0);
370
}
371
template <bool isSigned>
372
5097
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::allOnes(const bwt& w)
373
{
374
5097
  return symbolicBitVector<isSigned>(~zero(w));
375
}
376
377
template <bool isSigned>
378
1487
symbolicProposition symbolicBitVector<isSigned>::isAllOnes() const
379
{
380
1487
  return (*this == symbolicBitVector<isSigned>::allOnes(this->getWidth()));
381
}
382
template <bool isSigned>
383
11437
symbolicProposition symbolicBitVector<isSigned>::isAllZeros() const
384
{
385
11437
  return (*this == symbolicBitVector<isSigned>::zero(this->getWidth()));
386
}
387
388
template <>
389
75
symbolicBitVector<true> symbolicBitVector<true>::maxValue(const bwt& w)
390
{
391
150
  symbolicBitVector<true> leadingZero(symbolicBitVector<true>::zero(1));
392
150
  symbolicBitVector<true> base(symbolicBitVector<true>::allOnes(w - 1));
393
394
150
  return symbolicBitVector<true>(::cvc5::NodeManager::currentNM()->mkNode(
395
150
      ::cvc5::kind::BITVECTOR_CONCAT, leadingZero, base));
396
}
397
398
template <>
399
4
symbolicBitVector<false> symbolicBitVector<false>::maxValue(const bwt& w)
400
{
401
4
  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
72106
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator<<(
423
    const symbolicBitVector<isSigned>& op) const
424
{
425
  return symbolicBitVector<isSigned>(
426
72106
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_SHL, *this, op));
427
}
428
429
template <bool isSigned>
430
3254
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator>>(
431
    const symbolicBitVector<isSigned>& op) const
432
{
433
  return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
434
3254
      (isSigned) ? kind::BITVECTOR_ASHR : kind::BITVECTOR_LSHR, *this, op));
435
}
436
437
template <bool isSigned>
438
60966
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator|(
439
    const symbolicBitVector<isSigned>& op) const
440
{
441
  return symbolicBitVector<isSigned>(
442
60966
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_OR, *this, op));
443
}
444
445
template <bool isSigned>
446
10707
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator&(
447
    const symbolicBitVector<isSigned>& op) const
448
{
449
  return symbolicBitVector<isSigned>(
450
10707
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_AND, *this, op));
451
}
452
453
template <bool isSigned>
454
4045
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator+(
455
    const symbolicBitVector<isSigned>& op) const
456
{
457
  return symbolicBitVector<isSigned>(
458
4045
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_ADD, *this, op));
459
}
460
461
template <bool isSigned>
462
93106
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator-(
463
    const symbolicBitVector<isSigned>& op) const
464
{
465
  return symbolicBitVector<isSigned>(
466
93106
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_SUB, *this, op));
467
}
468
469
template <bool isSigned>
470
25
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator*(
471
    const symbolicBitVector<isSigned>& op) const
472
{
473
  return symbolicBitVector<isSigned>(
474
25
      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
41485
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator-(void) const
495
{
496
  return symbolicBitVector<isSigned>(
497
41485
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_NEG, *this));
498
}
499
500
template <bool isSigned>
501
5317
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator~(void) const
502
{
503
  return symbolicBitVector<isSigned>(
504
5317
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, *this));
505
}
506
507
template <bool isSigned>
508
20
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::increment() const
509
{
510
  return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
511
20
      kind::BITVECTOR_ADD, *this, one(this->getWidth())));
512
}
513
514
template <bool isSigned>
515
5145
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::decrement() const
516
{
517
  return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
518
5145
      kind::BITVECTOR_SUB, *this, one(this->getWidth())));
519
}
520
521
template <bool isSigned>
522
264
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::signExtendRightShift(
523
    const symbolicBitVector<isSigned>& op) const
524
{
525
  return symbolicBitVector<isSigned>(
526
264
      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
5453
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularLeftShift(
533
    const symbolicBitVector<isSigned>& op) const
534
{
535
5453
  return *this << op;
536
}
537
538
template <bool isSigned>
539
35
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularRightShift(
540
    const symbolicBitVector<isSigned>& op) const
541
{
542
35
  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
5015
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularDecrement()
554
    const
555
{
556
5015
  return this->decrement();
557
}
558
559
template <bool isSigned>
560
695
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularAdd(
561
    const symbolicBitVector<isSigned>& op) const
562
{
563
695
  return *this + op;
564
}
565
566
template <bool isSigned>
567
682
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularNegate() const
568
{
569
682
  return -(*this);
570
}
571
572
/*** Comparisons ***/
573
574
template <bool isSigned>
575
153740
symbolicProposition symbolicBitVector<isSigned>::operator==(
576
    const symbolicBitVector<isSigned>& op) const
577
{
578
  return symbolicProposition(
579
153740
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_COMP, *this, op));
580
}
581
582
template <bool isSigned>
583
58401
symbolicProposition symbolicBitVector<isSigned>::operator<=(
584
    const symbolicBitVector<isSigned>& op) const
585
{
586
  // Consider adding kind::BITVECTOR_SLEBV and BITVECTOR_ULEBV
587
58401
  return (*this < op) || (*this == op);
588
}
589
590
template <bool isSigned>
591
5865
symbolicProposition symbolicBitVector<isSigned>::operator>=(
592
    const symbolicBitVector<isSigned>& op) const
593
{
594
5865
  return (*this > op) || (*this == op);
595
}
596
597
template <bool isSigned>
598
58991
symbolicProposition symbolicBitVector<isSigned>::operator<(
599
    const symbolicBitVector<isSigned>& op) const
600
{
601
  return symbolicProposition(NodeManager::currentNM()->mkNode(
602
58991
      (isSigned) ? kind::BITVECTOR_SLTBV : kind::BITVECTOR_ULTBV, *this, op));
603
}
604
605
template <bool isSigned>
606
6663
symbolicProposition symbolicBitVector<isSigned>::operator>(
607
    const symbolicBitVector<isSigned>& op) const
608
{
609
  return symbolicProposition(NodeManager::currentNM()->mkNode(
610
6663
      (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
93
symbolicBitVector<true> symbolicBitVector<isSigned>::toSigned(void) const
617
{
618
93
  return symbolicBitVector<true>(*this);
619
}
620
template <bool isSigned>
621
11362
symbolicBitVector<false> symbolicBitVector<isSigned>::toUnsigned(void) const
622
{
623
11362
  return symbolicBitVector<false>(*this);
624
}
625
626
/*** Bit hacks ***/
627
template <>
628
972
symbolicBitVector<true> symbolicBitVector<true>::extend(bwt extension) const
629
{
630
1944
  NodeBuilder construct(kind::BITVECTOR_SIGN_EXTEND);
631
2916
  construct << NodeManager::currentNM()->mkConst<BitVectorSignExtend>(
632
3888
      BitVectorSignExtend(extension))
633
972
            << *this;
634
635
1944
  return symbolicBitVector<true>(construct);
636
}
637
638
template <>
639
13778
symbolicBitVector<false> symbolicBitVector<false>::extend(bwt extension) const
640
{
641
27556
  NodeBuilder construct(kind::BITVECTOR_ZERO_EXTEND);
642
41334
  construct << NodeManager::currentNM()->mkConst<BitVectorZeroExtend>(
643
55112
      BitVectorZeroExtend(extension))
644
13778
            << *this;
645
646
27556
  return symbolicBitVector<false>(construct);
647
}
648
649
template <bool isSigned>
650
94
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::contract(
651
    bwt reduction) const
652
{
653
94
  Assert(this->getWidth() > reduction);
654
655
188
  NodeBuilder construct(kind::BITVECTOR_EXTRACT);
656
376
  construct << NodeManager::currentNM()->mkConst<BitVectorExtract>(
657
94
      BitVectorExtract((this->getWidth() - 1) - reduction, 0))
658
188
            << *this;
659
660
188
  return symbolicBitVector<isSigned>(construct);
661
}
662
663
template <bool isSigned>
664
5125
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::resize(
665
    bwt newSize) const
666
{
667
5125
  bwt width = this->getWidth();
668
669
5125
  if (newSize > width)
670
  {
671
5121
    return this->extend(newSize - width);
672
  }
673
4
  else if (newSize < width)
674
  {
675
4
    return this->contract(width - newSize);
676
  }
677
  else
678
  {
679
    return *this;
680
  }
681
}
682
683
template <bool isSigned>
684
8514
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::matchWidth(
685
    const symbolicBitVector<isSigned>& op) const
686
{
687
8514
  Assert(this->getWidth() <= op.getWidth());
688
8514
  return this->extend(op.getWidth() - this->getWidth());
689
}
690
691
template <bool isSigned>
692
67739
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::append(
693
    const symbolicBitVector<isSigned>& op) const
694
{
695
  return symbolicBitVector<isSigned>(
696
67739
      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
143066
symbolicBitVector<isSigned> symbolicBitVector<isSigned>::extract(
702
    bwt upper, bwt lower) const
703
{
704
143066
  Assert(upper >= lower);
705
706
286132
  NodeBuilder construct(kind::BITVECTOR_EXTRACT);
707
429198
  construct << NodeManager::currentNM()->mkConst<BitVectorExtract>(
708
      BitVectorExtract(upper, lower))
709
286132
            << *this;
710
711
286132
  return symbolicBitVector<isSigned>(construct);
712
}
713
714
3912
floatingPointTypeInfo::floatingPointTypeInfo(const TypeNode type)
715
3912
    : FloatingPointSize(type.getConst<FloatingPointSize>())
716
{
717
3912
  Assert(type.isFloatingPoint());
718
3912
}
719
63
floatingPointTypeInfo::floatingPointTypeInfo(unsigned exp, unsigned sig)
720
63
    : FloatingPointSize(exp, sig)
721
{
722
63
}
723
floatingPointTypeInfo::floatingPointTypeInfo(const floatingPointTypeInfo& old)
724
    : FloatingPointSize(old)
725
{
726
}
727
728
3144
TypeNode floatingPointTypeInfo::getTypeNode(void) const
729
{
730
3144
  return NodeManager::currentNM()->mkFloatingPointType(*this);
731
}
732
}  // namespace symfpuSymbolic
733
734
9940
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
9940
      d_sbvMap(user)
741
{
742
9940
}
743
744
9937
FpWordBlaster::~FpWordBlaster() {}
745
746
3144
Node FpWordBlaster::ufToNode(const fpt& format, const uf& u) const
747
{
748
3144
  NodeManager* nm = NodeManager::currentNM();
749
750
3144
  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
6288
  ubv packed(symfpu::pack<traits>(format, u));
757
  Node value =
758
3144
      nm->mkNode(nm->mkConst(FloatingPointToFPIEEEBitVector(fps)), packed);
759
6288
  return value;
760
}
761
762
153
Node FpWordBlaster::rmToNode(const rm& r) const
763
{
764
153
  NodeManager* nm = NodeManager::currentNM();
765
766
306
  Node transVar = r;
767
768
306
  Node RNE = traits::RNE();
769
306
  Node RNA = traits::RNA();
770
306
  Node RTP = traits::RTP();
771
306
  Node RTN = traits::RTN();
772
306
  Node RTZ = traits::RTZ();
773
774
  Node value = nm->mkNode(
775
      kind::ITE,
776
306
      nm->mkNode(kind::EQUAL, transVar, RNE),
777
306
      nm->mkConst(RoundingMode::ROUND_NEAREST_TIES_TO_EVEN),
778
918
      nm->mkNode(
779
          kind::ITE,
780
306
          nm->mkNode(kind::EQUAL, transVar, RNA),
781
306
          nm->mkConst(RoundingMode::ROUND_NEAREST_TIES_TO_AWAY),
782
918
          nm->mkNode(
783
              kind::ITE,
784
306
              nm->mkNode(kind::EQUAL, transVar, RTP),
785
306
              nm->mkConst(RoundingMode::ROUND_TOWARD_POSITIVE),
786
918
              nm->mkNode(kind::ITE,
787
306
                         nm->mkNode(kind::EQUAL, transVar, RTN),
788
306
                         nm->mkConst(RoundingMode::ROUND_TOWARD_NEGATIVE),
789
1071
                         nm->mkConst(RoundingMode::ROUND_TOWARD_ZERO)))));
790
306
  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
131
FpWordBlaster::uf FpWordBlaster::buildComponents(TNode current)
804
{
805
131
  Assert(Theory::isLeafOf(current, THEORY_FP)
806
         || current.getKind() == kind::FLOATINGPOINT_TO_FP_REAL);
807
808
131
  NodeManager* nm = NodeManager::currentNM();
809
262
  uf tmp(nm->mkNode(kind::FLOATINGPOINT_COMPONENT_NAN, current),
810
262
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_INF, current),
811
262
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_ZERO, current),
812
262
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_SIGN, current),
813
262
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_EXPONENT, current),
814
1441
         nm->mkNode(kind::FLOATINGPOINT_COMPONENT_SIGNIFICAND, current));
815
816
131
  d_additionalAssertions.push_back(tmp.valid(fpt(current.getType())));
817
818
131
  return tmp;
819
}
820
821
2094
Node FpWordBlaster::wordBlast(TNode node)
822
{
823
4188
  std::vector<TNode> visit;
824
4188
  std::unordered_map<TNode, bool> visited;
825
2094
  NodeManager* nm = NodeManager::currentNM();
826
827
2094
  visit.push_back(node);
828
829
17162
  while (!visit.empty())
830
  {
831
12760
    TNode cur = visit.back();
832
7534
    visit.pop_back();
833
12760
    TypeNode t(cur.getType());
834
835
    /* Already word-blasted, skip. */
836
16446
    if ((t.isBoolean() && d_boolMap.find(cur) != d_boolMap.end())
837
15068
        || (t.isRoundingMode() && d_rmMap.find(cur) != d_rmMap.end())
838
7426
        || (t.isBitVector()
839
10056
            && (d_sbvMap.find(cur) != d_sbvMap.end()
840
10056
                || d_ubvMap.find(cur) != d_ubvMap.end()))
841
22494
        || (t.isFloatingPoint() && d_fpMap.find(cur) != d_fpMap.end()))
842
    {
843
2308
      continue;
844
    }
845
846
5226
    Kind kind = cur.getKind();
847
848
5226
    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
      continue;
862
    }
863
864
5226
    auto it = visited.find(cur);
865
5226
    if (it == visited.end())
866
    {
867
2613
      visited.emplace(cur, 0);
868
2613
      visit.push_back(cur);
869
2613
      visit.insert(visit.end(), cur.begin(), cur.end());
870
    }
871
2613
    else if (it->second == false)
872
    {
873
2613
      it->second = true;
874
875
2613
      if (t.isRoundingMode())
876
      {
877
        /* ---- RoundingMode constants and variables -------------- */
878
49
        Assert(Theory::isLeafOf(cur, THEORY_FP));
879
49
        if (kind == kind::CONST_ROUNDINGMODE)
880
        {
881
28
          switch (cur.getConst<RoundingMode>())
882
          {
883
16
            case RoundingMode::ROUND_NEAREST_TIES_TO_EVEN:
884
16
              d_rmMap.insert(cur, traits::RNE());
885
16
              break;
886
4
            case RoundingMode::ROUND_NEAREST_TIES_TO_AWAY:
887
4
              d_rmMap.insert(cur, traits::RNA());
888
4
              break;
889
4
            case RoundingMode::ROUND_TOWARD_POSITIVE:
890
4
              d_rmMap.insert(cur, traits::RTP());
891
4
              break;
892
            case RoundingMode::ROUND_TOWARD_NEGATIVE:
893
              d_rmMap.insert(cur, traits::RTN());
894
              break;
895
4
            case RoundingMode::ROUND_TOWARD_ZERO:
896
4
              d_rmMap.insert(cur, traits::RTZ());
897
4
              break;
898
            default: Unreachable() << "Unknown rounding mode"; break;
899
          }
900
        }
901
        else
902
        {
903
42
          rm tmp(nm->mkNode(kind::ROUNDINGMODE_BITBLAST, cur));
904
21
          d_rmMap.insert(cur, tmp);
905
21
          d_additionalAssertions.push_back(tmp.valid());
906
        }
907
      }
908
2564
      else if (t.isFloatingPoint())
909
      {
910
        /* ---- FloatingPoint constants and variables ------------- */
911
523
        if (Theory::isLeafOf(cur, THEORY_FP))
912
        {
913
390
          if (kind == kind::CONST_FLOATINGPOINT)
914
          {
915
518
            d_fpMap.insert(
916
                cur,
917
518
                symfpu::unpackedFloat<traits>(
918
259
                    cur.getConst<FloatingPoint>().getLiteral()->getSymUF()));
919
          }
920
          else
921
          {
922
131
            d_fpMap.insert(cur, buildComponents(cur));
923
          }
924
        }
925
        else
926
        {
927
          /* ---- FloatingPoint operators --------------------------- */
928
133
          Assert(kind != kind::CONST_FLOATINGPOINT);
929
133
          Assert(kind != kind::VARIABLE);
930
133
          Assert(kind != kind::BOUND_VARIABLE && kind != kind::SKOLEM);
931
932
133
          switch (kind)
933
          {
934
            /* ---- Arithmetic operators ---- */
935
15
            case kind::FLOATINGPOINT_ABS:
936
15
              Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
937
30
              d_fpMap.insert(cur,
938
45
                             symfpu::absolute<traits>(
939
45
                                 fpt(t), (*d_fpMap.find(cur[0])).second));
940
15
              break;
941
942
15
            case kind::FLOATINGPOINT_NEG:
943
15
              Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
944
30
              d_fpMap.insert(cur,
945
45
                             symfpu::negate<traits>(
946
45
                                 fpt(t), (*d_fpMap.find(cur[0])).second));
947
15
              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
20
            case kind::FLOATINGPOINT_RTI:
960
20
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
961
20
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
962
40
              d_fpMap.insert(cur,
963
80
                             symfpu::roundToIntegral<traits>(
964
40
                                 fpt(t),
965
40
                                 (*d_rmMap.find(cur[0])).second,
966
40
                                 (*d_fpMap.find(cur[1])).second));
967
20
              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
25
            case kind::FLOATINGPOINT_ADD:
1002
25
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1003
25
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1004
25
              Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
1005
50
              d_fpMap.insert(cur,
1006
100
                             symfpu::add<traits>(fpt(t),
1007
50
                                                 (*d_rmMap.find(cur[0])).second,
1008
50
                                                 (*d_fpMap.find(cur[1])).second,
1009
50
                                                 (*d_fpMap.find(cur[2])).second,
1010
50
                                                 prop(true)));
1011
25
              break;
1012
1013
13
            case kind::FLOATINGPOINT_MULT:
1014
13
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1015
13
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1016
13
              Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
1017
26
              d_fpMap.insert(
1018
                  cur,
1019
52
                  symfpu::multiply<traits>(fpt(t),
1020
26
                                           (*d_rmMap.find(cur[0])).second,
1021
26
                                           (*d_fpMap.find(cur[1])).second,
1022
26
                                           (*d_fpMap.find(cur[2])).second));
1023
13
              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
16
            case kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR:
1077
16
              Assert(cur[0].getType().isBitVector());
1078
16
              d_fpMap.insert(cur, symfpu::unpack<traits>(fpt(t), ubv(cur[0])));
1079
16
              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
8
            case kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR:
1090
8
              Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1091
16
              d_fpMap.insert(
1092
                  cur,
1093
40
                  symfpu::convertUBVToFloat<traits>(
1094
24
                      fpt(t), (*d_rmMap.find(cur[0])).second, ubv(cur[1])));
1095
8
              break;
1096
1097
            case kind::FLOATINGPOINT_TO_FP_REAL:
1098
              d_fpMap.insert(cur, buildComponents(cur));
1099
              // Rely on the real theory and theory combination
1100
              // to handle the value
1101
              break;
1102
1103
            default: Unreachable() << "Unhandled kind " << kind; break;
1104
          }
1105
        }
1106
      }
1107
2041
      else if (t.isBoolean())
1108
      {
1109
689
        switch (kind)
1110
        {
1111
          /* ---- Comparisons --------------------------------------- */
1112
548
          case kind::EQUAL:
1113
          {
1114
1096
            TypeNode childType(cur[0].getType());
1115
1116
548
            if (childType.isFloatingPoint())
1117
            {
1118
357
              Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1119
357
              Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1120
714
              d_boolMap.insert(
1121
                  cur,
1122
1071
                  symfpu::smtlibEqual<traits>(fpt(childType),
1123
714
                                              (*d_fpMap.find(cur[0])).second,
1124
714
                                              (*d_fpMap.find(cur[1])).second));
1125
            }
1126
191
            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
548
            }
1134
            // else do nothing
1135
          }
1136
548
          break;
1137
1138
44
          case kind::FLOATINGPOINT_LEQ:
1139
44
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1140
44
            Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1141
88
            d_boolMap.insert(cur,
1142
176
                             symfpu::lessThanOrEqual<traits>(
1143
88
                                 fpt(cur[0].getType()),
1144
88
                                 (*d_fpMap.find(cur[0])).second,
1145
88
                                 (*d_fpMap.find(cur[1])).second));
1146
44
            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
7
          case kind::FLOATINGPOINT_ISZ:
1176
7
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1177
14
            d_boolMap.insert(
1178
                cur,
1179
14
                symfpu::isZero<traits>(fpt(cur[0].getType()),
1180
14
                                       (*d_fpMap.find(cur[0])).second));
1181
7
            break;
1182
1183
30
          case kind::FLOATINGPOINT_ISINF:
1184
30
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1185
60
            d_boolMap.insert(
1186
                cur,
1187
60
                symfpu::isInfinite<traits>(fpt(cur[0].getType()),
1188
60
                                           (*d_fpMap.find(cur[0])).second));
1189
30
            break;
1190
1191
24
          case kind::FLOATINGPOINT_ISNAN:
1192
24
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1193
48
            d_boolMap.insert(
1194
                cur,
1195
48
                symfpu::isNaN<traits>(fpt(cur[0].getType()),
1196
48
                                      (*d_fpMap.find(cur[0])).second));
1197
24
            break;
1198
1199
23
          case kind::FLOATINGPOINT_ISNEG:
1200
23
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1201
46
            d_boolMap.insert(
1202
                cur,
1203
46
                symfpu::isNegative<traits>(fpt(cur[0].getType()),
1204
46
                                           (*d_fpMap.find(cur[0])).second));
1205
23
            break;
1206
1207
5
          case kind::FLOATINGPOINT_ISPOS:
1208
5
            Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
1209
10
            d_boolMap.insert(
1210
                cur,
1211
10
                symfpu::isPositive<traits>(fpt(cur[0].getType()),
1212
10
                                           (*d_fpMap.find(cur[0])).second));
1213
5
            break;
1214
1215
689
          default:;  // do nothing
1216
        }
1217
      }
1218
1352
      else if (t.isBitVector())
1219
      {
1220
        /* ---- Conversions --------------------------------------- */
1221
1261
        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
1261
        else if (kind == kind::FLOATINGPOINT_TO_SBV_TOTAL)
1236
        {
1237
4
          Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
1238
4
          Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
1239
          FloatingPointToSBVTotal info =
1240
4
              cur.getOperator().getConst<FloatingPointToSBVTotal>();
1241
1242
8
          d_sbvMap.insert(
1243
              cur,
1244
20
              symfpu::convertFloatToSBV<traits>(fpt(cur[1].getType()),
1245
8
                                                (*d_rmMap.find(cur[0])).second,
1246
8
                                                (*d_fpMap.find(cur[1])).second,
1247
                                                info.d_bv_size,
1248
8
                                                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
2094
  if (d_boolMap.find(node) != d_boolMap.end())
1261
  {
1262
498
    Assert(node.getType().isBoolean());
1263
498
    return (*d_boolMap.find(node)).second;
1264
  }
1265
1596
  if (d_sbvMap.find(node) != d_sbvMap.end())
1266
  {
1267
4
    Assert(node.getKind() == kind::FLOATINGPOINT_TO_SBV_TOTAL);
1268
4
    return (*d_sbvMap.find(node)).second;
1269
  }
1270
1592
  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
1592
  return node;
1276
}
1277
1278
3297
Node FpWordBlaster::getValue(Valuation& val, TNode var)
1279
{
1280
3297
  Assert(Theory::isLeafOf(var, THEORY_FP));
1281
1282
6594
  TypeNode t(var.getType());
1283
1284
3297
  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
3297
  if (t.isRoundingMode())
1289
  {
1290
153
    rmMap::const_iterator i(d_rmMap.find(var));
1291
153
    if (i == d_rmMap.end())
1292
    {
1293
      return Node::null();
1294
    }
1295
153
    return rmToNode((*i).second);
1296
  }
1297
1298
3144
  fpMap::const_iterator i(d_fpMap.find(var));
1299
3144
  if (i == d_fpMap.end())
1300
  {
1301
    return Node::null();
1302
  }
1303
3144
  return ufToNode(fpt(t), (*i).second);
1304
}
1305
1306
}  // namespace fp
1307
}  // namespace theory
1308
29574
}  // namespace cvc5