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