1 // Copyright 2017-2019 VMware, Inc.
2 // SPDX-License-Identifier: BSD-2-Clause
3 //
4 // The BSD-2 license (the License) set forth below applies to all parts of the
5 // Cascade project.  You may not use this file except in compliance with the
6 // License.
7 //
8 // BSD-2 License
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright notice, this
14 // list of conditions and the following disclaimer.
15 //
16 // 2. Redistributions in binary form must reproduce the above copyright notice,
17 // this list of conditions and the following disclaimer in the documentation
18 // and/or other materials provided with the distribution.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
21 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #ifndef CASCADE_SRC_COMMON_BITS_H
32 #define CASCADE_SRC_COMMON_BITS_H
33 
34 #include <algorithm>
35 #include <cassert>
36 #include <cctype>
37 #include <cmath>
38 #include <iostream>
39 #include <stdint.h>
40 #include <string>
41 #include <type_traits>
42 #include <vector>
43 #include "common/serializable.h"
44 #include "common/vector.h"
45 
46 namespace cascade {
47 
48 // This class is the fundamental representation of a bit string.
49 
50 template <typename T, typename BT, typename ST>
51 class BitsBase : public Serializable {
52   public:
53     // Supporting Concepts:
54     enum class Type : uint8_t {
55       UNSIGNED = 0,
56       SIGNED,
57       REAL
58     };
59 
60     // Constructors:
61     BitsBase();
62     explicit BitsBase(size_t n, Type t);
63     explicit BitsBase(bool b);
64     explicit BitsBase(char c);
65     explicit BitsBase(double d);
66     explicit BitsBase(const std::string& s);
67     explicit BitsBase(size_t n, T val);
68 
69     // Compiler-Generated Constructors:
70     BitsBase(const BitsBase& rhs) = default;
71     BitsBase(BitsBase&& rhs) = default;
72     BitsBase& operator=(const BitsBase& rhs) = default;
73     BitsBase& operator=(BitsBase&& rhs) = default;
74     ~BitsBase() override = default;
75 
76     // Serial I/O:
77     void read(std::istream& is, size_t base);
78     void write(std::ostream& os, size_t base) const;
79     size_t deserialize(std::istream& is) override;
80     size_t serialize(std::ostream& os) const override;
81 
82     // Block I/O:
83     template <typename B>
84     B read_word(size_t n) const;
85     template <typename B>
86     void write_word(size_t n, B b);
87 
88     // Value I/O:
89     void read(char c);
90 
91     // Type Introspection:
92     size_t size() const;
93     Type get_type() const;
94     bool is_signed() const;
95     bool is_real() const;
96 
97     // Native Casts:
98     bool to_bool() const;
99     char to_char() const;
100     double to_double() const;
101     std::string to_string() const;
102     T to_uint() const;
103 
104     // Verilog Casts:
105     void resize(size_t n);
106     void cast_type(Type t);
107     void reinterpret_type(Type t);
108 
109     // Bitwise Operators:
110     //
111     // Apply a bitwise operator to operands and store the result here.  These
112     // methods assume equivalent bit-width between operands and destination and
113     // do not sign extend. These methods are undefined for reals.
114     void bitwise_and(const BitsBase& lhs, const BitsBase& rhs);
115     void bitwise_or(const BitsBase& lhs, const BitsBase& rhs);
116     void bitwise_xor(const BitsBase& lhs, const BitsBase& rhs);
117     void bitwise_xnor(const BitsBase& lhs, const BitsBase& rhs);
118     void bitwise_sll(const BitsBase& lhs, const BitsBase& rhs);
119     void bitwise_sal(const BitsBase& lhs, const BitsBase& rhs);
120     void bitwise_slr(const BitsBase& lhs, const BitsBase& rhs);
121     void bitwise_sar(const BitsBase& lhs, const BitsBase& rhs);
122     void bitwise_not(const BitsBase& lhs);
123 
124     // Arithmetic Operators:
125     //
126     // Apply an arithmetic operator to operands and store the result here.
127     // These methods all assume equivalent bit-width between operands and
128     // destination and do not sign extend. These methods all work on signed,
129     // unsigned, and real values (with the exception of mod).
130     void arithmetic_plus(const BitsBase& lhs);
131     void arithmetic_plus(const BitsBase& lhs, const BitsBase& rhs);
132     void arithmetic_minus(const BitsBase& lhs);
133     void arithmetic_minus(const BitsBase& lhs, const BitsBase& rhs);
134     void arithmetic_multiply(const BitsBase& lhs, const BitsBase& rhs);
135     void arithmetic_divide(const BitsBase& lhs, const BitsBase& rhs);
136     void arithmetic_mod(const BitsBase& lhs, const BitsBase& rhs);
137     void arithmetic_pow(const BitsBase& lhs, const BitsBase& rhs);
138 
139     // Logical Operators:
140     //
141     // Apply a logical operator to operands and store the result here.  These
142     // methods all assume equivalent bit-width between operands and do not
143     // perform sign extension.  These methods all work on signed, unsigned, and
144     // real values, but assume that their desintation is not real.
145     void logical_and(const BitsBase& lhs, const BitsBase& rhs);
146     void logical_or(const BitsBase& lhs, const BitsBase& rhs);
147     void logical_not(const BitsBase& lhs);
148     void logical_eq(const BitsBase& lhs, const BitsBase& rhs);
149     void logical_ne(const BitsBase& lhs, const BitsBase& rhs);
150     void logical_lt(const BitsBase& lhs, const BitsBase& rhs);
151     void logical_lte(const BitsBase& lhs, const BitsBase& rhs);
152     void logical_gt(const BitsBase& lhs, const BitsBase& rhs);
153     void logical_gte(const BitsBase& lhs, const BitsBase& rhs);
154 
155     // Reduction Operators:
156     //
157     // Apply a reduction operator to an operand and store the result here.
158     // These methods all assume single bit-width in their destination and do
159     // not perform sign extension. These methods are undefined for real values.
160     void reduce_and(const BitsBase& lhs);
161     void reduce_nand(const BitsBase& lhs);
162     void reduce_or(const BitsBase& lhs);
163     void reduce_nor(const BitsBase& lhs);
164     void reduce_xor(const BitsBase& lhs);
165     void reduce_xnor(const BitsBase& lhs);
166 
167     // Concatenation Operations:
168     //
169     // Concatenate two variables. This method is undefined for real values.
170     void concat(const BitsBase& rhs);
171 
172     // Comparison Operators:
173     //
174     // Check for value equality. These methods make no assumptions with respect
175     // to size or type and cast rhs as necessary.
176     bool eq(const BitsBase& rhs) const;
177     bool eq(size_t idx, const BitsBase& rhs) const;
178     bool eq(size_t msb, size_t lsb, const BitsBase& rhs) const;
179 
180     // Assignment Operators:
181     //
182     // Assign bits. These methods make no assumptions made with respect to
183     // sizes and handle sign-extension and type conversion as necessary.
184     // Subscripting operations are undefined for real operands.
185     //
186     // TODO(eschkufz> The latter two methods are undefined for reals period.
187     // This is to simplify their implementation based on the limited context in
188     // which they are called. Is this asymmetry masking a more elegant
189     // implementation?
190     void assign(const BitsBase& rhs);
191     void assign(size_t idx, const BitsBase& rhs);
192     void assign(size_t msb, size_t lsb, const BitsBase& rhs);
193     void assign(const BitsBase& rhs, size_t idx);
194     void assign(const BitsBase& rhs, size_t msb, size_t lsb);
195 
196     // Copy Operators:
197     //
198     // Nothing fancy. Copies the state of the rhs.
199     void copy(const BitsBase& rhs);
200 
201     // Bitwise Operators:
202     //
203     // These operators are meant for use outside of the constraints imposed by
204     // the verilog semantics for variables and have no restrictions on type.
205     bool get(size_t idx) const;
206     void set(size_t idx, bool b);
207     void flip(size_t idx);
208 
209     // Built-in Comparison Operators:
210     //
211     // Logical comparison, assumes equal operand sizes and types for integer
212     // valeus.  Will automatically cast reals to integers as necessary.
213     bool operator==(const BitsBase& rhs) const;
214     bool operator!=(const BitsBase& rhs) const;
215     bool operator<(const BitsBase& rhs) const;
216     bool operator<=(const BitsBase& rhs) const;
217     bool operator>(const BitsBase& rhs) const;
218     bool operator>=(const BitsBase& rhs) const;
219 
220   private:
221     // Bit-string representation
222     Vector<T> val_;
223     // Total number of bits in this string
224     uint32_t size_;
225     // How is this value being interpreted
226     Type type_;
227 
228     // Reads a real number, sets size to 64
229     void read_real(std::istream& is);
230     // Reads an unsigned number in base 2, 8, or 16, sets size based on result
231     void read_2_8_16(std::istream& is, size_t base);
232     // Reads a number in base 10, sets size and type based on result
233     void read_10(std::istream& is);
234     // Writes a number as a real
235     void write_real(std::ostream& os) const;
236     // Writes a number in base 2, 8, or 16 as an unsigned value
237     void write_2_8_16(std::ostream& os, size_t base) const;
238     // Writes a number in base 10 as a signed or unsigned value
239     void write_10(std::ostream& os) const;
240     // Halves a decimal value, stored as a string
241     void dec_halve(std::string& s) const;
242     // Returns true if a decimal value, stored as a string is 0
243     bool dec_zero(const std::string& s) const;
244     // Doubles a decimal value, stored as a string in reverse order
245     void dec_double(std::string& s) const;
246     // Increments a decimal value, stored as a string in reverse order
247     void dec_inc(std::string& s) const;
248 
249     // Shift Helpers:
250     void bitwise_sll_const(const BitsBase& lhs, size_t samt);
251     void bitwise_sxr_const(const BitsBase& lhs, size_t samt, bool arith);
252 
253     // Returns the nth (possibly greater than val_.size()th) word of this value.
254     // Performs sign extension as necessary.
255     T signed_get(size_t n) const;
256 
257     // Returns true if this is a signed number with high order bit set
258     bool is_neg_signed() const;
259     // Zeros out bits with index greater than size_
260     void trim();
261     // Extends representation to n bits and zero pads
262     void extend_to(size_t n);
263     // Extends representation to n bits and sign extends if necessary
264     void sign_extend_to(size_t n);
265     // Shrinks size and calls trim
266     void shrink_to(size_t n);
267     // Shrinks to size one and sets val
268     void shrink_to_bool(bool b);
269     // Inverts bits and adds one
270     void invert_add_one();
271     // Updates size and type; sets value according to to_double().
272     void cast_int_to_real();
273     // Updates type according to arg, value and size according to_double().
274     void cast_real_to_int(bool s);
275 
276     // Returns the number of bits in a word
277     constexpr size_t bits_per_word() const;
278     // Returns the number of bytes in a word
279     constexpr size_t bytes_per_word() const;
280     // Returns the number of unique values representable by T as a double
281     constexpr double range() const;
282 };
283 
284 #ifdef __LP64__
285 using Bits = BitsBase<uint64_t, __uint128_t, int64_t>;
286 #else
287 using Bits = BitsBase<uint32_t, uint64_t, int32_t>;
288 #endif
289 
290 template <typename T, typename BT, typename ST>
BitsBase()291 inline BitsBase<T, BT, ST>::BitsBase() {
292   val_.push_back(0);
293   size_ = 1;
294   type_ = Type::UNSIGNED;
295 }
296 
297 template <typename T, typename BT, typename ST>
BitsBase(size_t n,Type t)298 inline BitsBase<T, BT, ST>::BitsBase(size_t n, Type t) {
299   if (type_ == Type::REAL) {
300     assert(n == 64);
301     val_.resize(64/bits_per_word());
302     *reinterpret_cast<double*>(val_.data()) = 0.0;
303   } else {
304     assert(n > 0);
305     val_.resize((n+bits_per_word()-1)/bits_per_word(), static_cast<T>(0));
306   }
307   size_ = n;
308   type_ = t;
309 }
310 
311 template <typename T, typename BT, typename ST>
BitsBase(bool b)312 inline BitsBase<T, BT, ST>::BitsBase(bool b) {
313   val_.push_back(b ? static_cast<T>(1) : static_cast<T>(0));
314   size_ = 1;
315   type_ = Type::UNSIGNED;
316 }
317 
318 template <typename T, typename BT, typename ST>
BitsBase(char c)319 inline BitsBase<T, BT, ST>::BitsBase(char c) {
320   val_.push_back(static_cast<T>(c));
321   size_ = 8;
322   type_ = Type::UNSIGNED;
323 }
324 
325 template <typename T, typename BT, typename ST>
BitsBase(double d)326 inline BitsBase<T, BT, ST>::BitsBase(double d) {
327   val_.resize(64/bits_per_word());
328   *reinterpret_cast<double*>(val_.data()) = d;
329   size_ = 64;
330   type_ = Type::REAL;
331 }
332 
333 template <typename T, typename BT, typename ST>
BitsBase(const std::string & s)334 inline BitsBase<T, BT, ST>::BitsBase(const std::string& s) {
335   val_.resize((s.length()+bytes_per_word()-1)/bytes_per_word(), static_cast<T>(0));
336   for (int pos = 0, i = s.length()-1; i >= 0; --i, ++pos) {
337     const auto idx = pos/bytes_per_word();
338     const auto off = 8*(pos%bytes_per_word());
339     val_[idx] |= (static_cast<T>(s[i]) << off);
340   }
341   size_ = 8*s.length();
342   type_ = Type::UNSIGNED;
343 }
344 
345 template <typename T, typename BT, typename ST>
BitsBase(size_t n,T val)346 inline BitsBase<T, BT, ST>::BitsBase(size_t n, T val) {
347   assert(n > 0);
348   val_.resize((n+bits_per_word()-1)/bits_per_word(), static_cast<T>(0));
349   val_[0] = val;
350   size_ = n;
351   type_ = Type::UNSIGNED;
352   trim();
353 }
354 
355 template <typename T, typename BT, typename ST>
read(std::istream & is,size_t base)356 inline void BitsBase<T, BT, ST>::read(std::istream& is, size_t base) {
357   switch (base) {
358     case 1:
359       return read_real(is);
360     case 2:
361     case 8:
362     case 16:
363       return read_2_8_16(is, base);
364     case 10:
365       return read_10(is);
366     default:
367       assert(false);
368   }
369 }
370 
371 template <typename T, typename BT, typename ST>
write(std::ostream & os,size_t base)372 inline void BitsBase<T, BT, ST>::write(std::ostream& os, size_t base) const {
373   switch (base) {
374     case 0:
375       return is_real() ? write_real(os) : write_10(os);
376     case 1:
377       return write_real(os);
378     case 2:
379     case 8:
380     case 16:
381       return write_2_8_16(os, base);
382     case 10:
383       return write_10(os);
384     default:
385       assert(false);
386   }
387 }
388 
389 template <typename T, typename BT, typename ST>
deserialize(std::istream & is)390 inline size_t BitsBase<T, BT, ST>::deserialize(std::istream& is) {
391   uint32_t header;
392   is.read(reinterpret_cast<char*>(&header), 4);
393 
394   shrink_to_bool(false);
395   extend_to(header & 0x3fffffffu);
396   type_ = static_cast<Type>(header >> 30);
397 
398   const auto n = (size_+7) / 8;
399   for (size_t i = 0; i < n; ++i) {
400     uint8_t b = is.get();
401     val_[i/bytes_per_word()] |= (static_cast<T>(b) << (8*(i%bytes_per_word())));
402   }
403 
404   return 4 + n;
405 }
406 
407 template <typename T, typename BT, typename ST>
serialize(std::ostream & os)408 inline size_t BitsBase<T, BT, ST>::serialize(std::ostream& os) const {
409   uint32_t header = size_ | (static_cast<uint32_t>(type_) << 30);
410   os.write(reinterpret_cast<char*>(&header), 4);
411 
412   const auto n = (size_+7) / 8;
413   for (size_t i = 0; i < n; ++i) {
414     const uint8_t b = (val_[i/bytes_per_word()] >> (8*(i%bytes_per_word()))) & static_cast<T>(0xffu);
415     os.put(b);
416   }
417 
418   return 4 + n;
419 }
420 
421 template <typename T, typename BT, typename ST>
422 template <typename B>
read_word(size_t n)423 inline B BitsBase<T, BT, ST>::read_word(size_t n) const {
424   assert(sizeof(B) <= sizeof(T));
425 
426   // Easy Case:
427   if (sizeof(B) == sizeof(T)) {
428     assert(n < val_.size());
429     return val_[n];
430   }
431 
432   // Hard Case:
433   const auto b_per_word = sizeof(T) / sizeof(B);
434   const auto idx = n / b_per_word;
435   const auto off = n % b_per_word;
436 
437   assert(idx < val_.size());
438   return val_[idx] >> (8*sizeof(B)*off);
439 }
440 
441 template <typename T, typename BT, typename ST>
442 template <typename B>
write_word(size_t n,B b)443 inline void BitsBase<T, BT, ST>::write_word(size_t n, B b) {
444   assert(sizeof(B) <= sizeof(T));
445 
446   // Easy Case:
447   if (sizeof(B) == sizeof(T)) {
448     assert(n < val_.size());
449     val_[n] = b;
450     return;
451   }
452 
453   // Hard Case:
454   const auto b_per_word = sizeof(T) / sizeof(B);
455   const auto idx = n / b_per_word;
456   const auto off = n % b_per_word;
457 
458   assert(idx < val_.size());
459   const T bmask = static_cast<B>(-1);
460   const auto mask = ~(bmask << (8*sizeof(B)*off));
461   val_[idx] &= mask;
462   val_[idx] |= (static_cast<T>(b) << (8*sizeof(B)*off));
463   trim();
464 }
465 
466 template <typename T, typename BT, typename ST>
read(char c)467 inline void BitsBase<T, BT, ST>::read(char c) {
468   val_.resize(1);
469   val_[0] = static_cast<T>(c);
470   size_ = 8;
471   type_ = Type::UNSIGNED;
472 }
473 
474 template <typename T, typename BT, typename ST>
size()475 inline size_t BitsBase<T, BT, ST>::size() const {
476   return size_;
477 }
478 
479 template <typename T, typename BT, typename ST>
get_type()480 inline typename BitsBase<T, BT, ST>::Type BitsBase<T, BT, ST>::get_type() const {
481   return type_;
482 }
483 
484 template <typename T, typename BT, typename ST>
is_signed()485 inline bool BitsBase<T, BT, ST>::is_signed() const {
486   return type_ != Type::UNSIGNED;
487 }
488 
489 template <typename T, typename BT, typename ST>
is_real()490 inline bool BitsBase<T, BT, ST>::is_real() const {
491   return type_ == Type::REAL;
492 }
493 
494 template <typename T, typename BT, typename ST>
to_bool()495 inline bool BitsBase<T, BT, ST>::to_bool() const {
496   // Special handling for real values.
497   if (type_ == Type::REAL) {
498     return *reinterpret_cast<const double*>(val_.data()) != 0.0;
499   }
500   // Otherwise check whether any bits are non-zero.
501   for (const auto& v : val_) {
502     if (v) {
503       return true;
504     }
505   }
506   return false;
507 }
508 
509 template <typename T, typename BT, typename ST>
to_char()510 inline char BitsBase<T, BT, ST>::to_char() const {
511   return static_cast<char>(to_uint() & 0xffu);
512 }
513 
514 template <typename T, typename BT, typename ST>
to_double()515 inline double BitsBase<T, BT, ST>::to_double() const {
516   switch (type_) {
517     case Type::SIGNED:
518       if (get(size_-1)) {
519         const_cast<BitsBase*>(this)->invert_add_one();
520         const_cast<BitsBase*>(this)->type_ = Type::UNSIGNED;
521         const auto res = to_double();
522         const_cast<BitsBase*>(this)->type_ = Type::SIGNED;
523         const_cast<BitsBase*>(this)->invert_add_one();
524         return res;
525       }
526       // Fallthrough...
527     case Type::UNSIGNED: {
528       double res = 0.0;
529       double base = 1.0;
530       for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
531         res += base * val_[i];
532         base *= range();
533       }
534       return res;
535     }
536     case Type::REAL:
537       return *reinterpret_cast<const double*>(val_.data());
538     default:
539       assert(false);
540       return 0;
541   }
542 }
543 
544 template <typename T, typename BT, typename ST>
to_string()545 inline std::string BitsBase<T, BT, ST>::to_string() const {
546   auto temp = *this;
547   // Cast real values to unsigned ints before printing.
548   if (type_ == Type::REAL) {
549     temp.cast_real_to_int(false);
550   }
551   // Pad values out to a multiple of 8 bits.
552   const auto trailing = temp.size() % 8;
553   if (trailing > 0) {
554     temp.sign_extend_to(temp.size() + 8 - trailing);
555   }
556   // Print characters, eight bits at a time.
557   std::string res(temp.size()/8, ' ');
558   for (int pos = 0, i = res.length()-1; i >= 0; --i, ++pos) {
559     const auto idx = pos/bytes_per_word();
560     const auto off = 8*(pos%bytes_per_word());
561     const auto val = (temp.val_[idx] >> off) & static_cast<T>(0xffu);
562     res[i] = ((val == 0) ? ' ' : static_cast<char>(val));
563   }
564   return res;
565 }
566 
567 template <typename T, typename BT, typename ST>
to_uint()568 inline T BitsBase<T, BT, ST>::to_uint() const {
569   switch (type_) {
570     case Type::UNSIGNED:
571     case Type::SIGNED:
572       return val_[0];
573     case Type::REAL:
574       return std::round(*reinterpret_cast<const double*>(val_.data()));
575     default:
576       assert(false);
577       return 0;
578   }
579 }
580 
581 template <typename T, typename BT, typename ST>
resize(size_t n)582 inline void BitsBase<T, BT, ST>::resize(size_t n) {
583   assert((type_ != Type::REAL) || (n == 64));
584   if (n < size_) {
585     shrink_to(n);
586   } else if (n > size_) {
587     sign_extend_to(n);
588   }
589 }
590 
591 template <typename T, typename BT, typename ST>
cast_type(Type t)592 inline void BitsBase<T, BT, ST>::cast_type(Type t) {
593   if (type_ == t) {
594     return;
595   } else if (t == Type::REAL) {
596     cast_int_to_real();
597   } else if (type_ == Type::REAL) {
598     cast_real_to_int(t == Type::SIGNED);
599   } else {
600     type_ = t;
601   }
602 }
603 
604 template <typename T, typename BT, typename ST>
reinterpret_type(Type t)605 inline void BitsBase<T, BT, ST>::reinterpret_type(Type t) {
606   if (type_ == t) {
607     return;
608   }
609   type_ = t;
610   if (type_ == Type::REAL) {
611     val_.resize(64/bits_per_word());
612   }
613 }
614 
615 template <typename T, typename BT, typename ST>
bitwise_and(const BitsBase & lhs,const BitsBase & rhs)616 inline void BitsBase<T, BT, ST>::bitwise_and(const BitsBase& lhs, const BitsBase& rhs) {
617   assert(!is_real() && !lhs.is_real() && !rhs.is_real());
618   assert(size() == lhs.size());
619   assert(size() == rhs.size());
620 
621   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
622     val_[i] = lhs.val_[i] & rhs.val_[i];
623   }
624 }
625 
626 template <typename T, typename BT, typename ST>
bitwise_or(const BitsBase & lhs,const BitsBase & rhs)627 inline void BitsBase<T, BT, ST>::bitwise_or(const BitsBase& lhs, const BitsBase& rhs) {
628   assert(!is_real() && !lhs.is_real() && !rhs.is_real());
629   assert(size() == lhs.size());
630   assert(size() == rhs.size());
631 
632   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
633     val_[i] = lhs.val_[i] | rhs.val_[i];
634   }
635 }
636 
637 template <typename T, typename BT, typename ST>
bitwise_xor(const BitsBase & lhs,const BitsBase & rhs)638 inline void BitsBase<T, BT, ST>::bitwise_xor(const BitsBase& lhs, const BitsBase& rhs) {
639   assert(!is_real() && !lhs.is_real() && !rhs.is_real());
640   assert(size() == lhs.size());
641   assert(size() == rhs.size());
642 
643   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
644     val_[i] = lhs.val_[i] ^ rhs.val_[i];
645   }
646 }
647 
648 template <typename T, typename BT, typename ST>
bitwise_xnor(const BitsBase & lhs,const BitsBase & rhs)649 inline void BitsBase<T, BT, ST>::bitwise_xnor(const BitsBase& lhs, const BitsBase& rhs) {
650   assert(!is_real() && !lhs.is_real() && !rhs.is_real());
651   assert(size() == lhs.size());
652   assert(size() == rhs.size());
653 
654   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
655     val_[i] = ~(lhs.val_[i] ^ rhs.val_[i]);
656   }
657   trim();
658 }
659 
660 template <typename T, typename BT, typename ST>
bitwise_sll(const BitsBase & lhs,const BitsBase & rhs)661 inline void BitsBase<T, BT, ST>::bitwise_sll(const BitsBase& lhs, const BitsBase& rhs) {
662   assert(!rhs.is_real());
663   const auto samt = rhs.to_uint();
664   bitwise_sll_const(lhs, samt);
665 }
666 
667 template <typename T, typename BT, typename ST>
bitwise_sal(const BitsBase & lhs,const BitsBase & rhs)668 inline void BitsBase<T, BT, ST>::bitwise_sal(const BitsBase& lhs, const BitsBase& rhs) {
669   // Equivalent to sll
670   bitwise_sll(lhs, rhs);
671 }
672 
673 template <typename T, typename BT, typename ST>
bitwise_slr(const BitsBase & lhs,const BitsBase & rhs)674 inline void BitsBase<T, BT, ST>::bitwise_slr(const BitsBase& lhs, const BitsBase& rhs) {
675   assert(!rhs.is_real());
676   const auto samt = rhs.to_uint();
677   bitwise_sxr_const(lhs, samt, false);
678 }
679 
680 template <typename T, typename BT, typename ST>
bitwise_sar(const BitsBase & lhs,const BitsBase & rhs)681 inline void BitsBase<T, BT, ST>::bitwise_sar(const BitsBase& lhs, const BitsBase& rhs) {
682   assert(!rhs.is_real());
683   const auto samt = rhs.to_uint();
684   bitwise_sxr_const(lhs, samt, true);
685 }
686 
687 template <typename T, typename BT, typename ST>
bitwise_not(const BitsBase & lhs)688 inline void BitsBase<T, BT, ST>::bitwise_not(const BitsBase& lhs) {
689   assert(!is_real() && !lhs.is_real());
690   assert(size() == lhs.size());
691 
692   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
693     val_[i] = ~lhs.val_[i];
694   }
695   trim();
696 }
697 
698 template <typename T, typename BT, typename ST>
arithmetic_plus(const BitsBase & lhs)699 inline void BitsBase<T, BT, ST>::arithmetic_plus(const BitsBase& lhs) {
700   // This is a copy; identical implementation for reals and integers
701   assert(size() == lhs.size());
702   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
703     val_[i] = lhs.val_[i];
704   }
705 }
706 
707 template <typename T, typename BT, typename ST>
arithmetic_plus(const BitsBase & lhs,const BitsBase & rhs)708 inline void BitsBase<T, BT, ST>::arithmetic_plus(const BitsBase& lhs, const BitsBase& rhs) {
709   if (lhs.is_real() || rhs.is_real()) {
710     assert(size() == 64);
711     *reinterpret_cast<double*>(val_.data()) = lhs.to_double() + rhs.to_double();
712     return;
713   }
714 
715   assert(size() == lhs.size());
716   assert(size() == rhs.size());
717 
718   T carry = 0;
719   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
720     val_[i] = lhs.val_[i] + rhs.val_[i] + carry;
721     if (carry) {
722       carry = (val_[i] <= lhs.val_[i]) ? static_cast<T>(1) : static_cast<T>(0);
723     } else {
724       carry = (val_[i] < lhs.val_[i]) ? static_cast<T>(1) : static_cast<T>(0);
725     }
726   }
727   trim();
728 }
729 
730 template <typename T, typename BT, typename ST>
arithmetic_minus(const BitsBase & lhs)731 inline void BitsBase<T, BT, ST>::arithmetic_minus(const BitsBase& lhs) {
732   if (lhs.is_real()) {
733     assert(size() == 64);
734     *reinterpret_cast<double*>(val_.data()) = -lhs.to_double();
735     return;
736   }
737 
738   assert(size() == lhs.size());
739 
740   T carry = 1;
741   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
742     val_[i] = ~lhs.val_[i];
743     const T sum = val_[i] + carry;
744     carry = (sum < val_[i]) ? static_cast<T>(1) : static_cast<T>(0);
745     val_[i] = sum;
746   }
747   trim();
748 }
749 
750 template <typename T, typename BT, typename ST>
arithmetic_minus(const BitsBase & lhs,const BitsBase & rhs)751 inline void BitsBase<T, BT, ST>::arithmetic_minus(const BitsBase& lhs, const BitsBase& rhs) {
752   if (lhs.is_real() || rhs.is_real()) {
753     assert(size() == 64);
754     *reinterpret_cast<double*>(val_.data()) = lhs.to_double() - rhs.to_double();
755     return;
756   }
757 
758   assert(size() == lhs.size());
759   assert(size() == rhs.size());
760 
761   T carry = 0;
762   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
763     val_[i] = lhs.val_[i] - rhs.val_[i] - carry;
764     if (carry) {
765       carry = (val_[i] >= lhs.val_[i]) ? static_cast<T>(1) : static_cast<T>(0);
766     } else {
767       carry = (val_[i] > lhs.val_[i]) ? static_cast<T>(1) : static_cast<T>(0);
768     }
769   }
770   trim();
771 }
772 
773 template <typename T, typename BT, typename ST>
arithmetic_multiply(const BitsBase & lhs,const BitsBase & rhs)774 inline void BitsBase<T, BT, ST>::arithmetic_multiply(const BitsBase& lhs, const BitsBase& rhs) {
775   if (lhs.is_real() || rhs.is_real()) {
776     assert(size() == 64);
777     *reinterpret_cast<double*>(val_.data()) = lhs.to_double() * rhs.to_double();
778     return;
779   }
780 
781   assert(size() == lhs.size());
782   assert(size() == rhs.size());
783 
784   // This is the optimized space algorithm described in wiki's multiplication
785   // algorithm article. The code is simplified here, as we can assume that both
786   // inputs and the result are capped at S words.
787 
788   const auto S = val_.size();
789   BT tot = 0;
790   for (size_t ri = 0; ri < S; ++ri) {
791     for (size_t bi = 0; bi <= ri; ++bi) {
792       size_t ai = ri - bi;
793       tot += static_cast<BT>(lhs.val_[ai]) * static_cast<BT>(rhs.val_[bi]);
794     }
795     val_[ri] = static_cast<T>(tot);
796     tot >>= bits_per_word();
797   }
798   trim();
799 }
800 
801 template <typename T, typename BT, typename ST>
arithmetic_divide(const BitsBase & lhs,const BitsBase & rhs)802 inline void BitsBase<T, BT, ST>::arithmetic_divide(const BitsBase& lhs, const BitsBase& rhs) {
803   if (lhs.is_real() || rhs.is_real()) {
804     assert(size() == 64);
805     *reinterpret_cast<double*>(val_.data()) = lhs.to_double() / rhs.to_double();
806     return;
807   }
808 
809   assert(size() == lhs.size());
810   assert(size() == rhs.size());
811 
812   // TODO(eschkufz) This only words for single word inputs
813   assert(val_.size() == 1);
814 
815   if ((lhs.type_ == Type::SIGNED) && (rhs.type_ == Type::SIGNED)) {
816     const ST l = lhs.is_neg_signed() ? (lhs.val_[0] | (static_cast<BT>(-1) << size_)) : lhs.val_[0];
817     const ST r = rhs.is_neg_signed() ? (rhs.val_[0] | (static_cast<BT>(-1) << rhs.size_)) : rhs.val_[0];
818     val_[0] = l / r;
819   } else {
820     val_[0] = lhs.val_[0] / rhs.val_[0];
821   }
822   trim();
823 }
824 
825 template <typename T, typename BT, typename ST>
arithmetic_mod(const BitsBase & lhs,const BitsBase & rhs)826 inline void BitsBase<T, BT, ST>::arithmetic_mod(const BitsBase& lhs, const BitsBase& rhs) {
827   assert(!lhs.is_real() && !rhs.is_real());
828   assert(size() == lhs.size());
829   assert(size() == rhs.size());
830 
831   // TODO(eschkufz) This only words for single word inputs
832   assert(val_.size() == 1);
833 
834   if ((lhs.type_ == Type::SIGNED) && (rhs.type_ == Type::SIGNED)) {
835     const ST l = lhs.is_neg_signed() ? (lhs.val_[0] | (static_cast<BT>(-1) << size_)) : lhs.val_[0];
836     const ST r = rhs.is_neg_signed() ? (rhs.val_[0] | (static_cast<BT>(-1) << rhs.size_)) : rhs.val_[0];
837     val_[0] = l % r;
838   } else {
839     val_[0] = lhs.val_[0] % rhs.val_[0];
840   }
841   trim();
842 }
843 
844 template <typename T, typename BT, typename ST>
arithmetic_pow(const BitsBase & lhs,const BitsBase & rhs)845 inline void BitsBase<T, BT, ST>::arithmetic_pow(const BitsBase& lhs, const BitsBase& rhs) {
846   // TODO(eschkufz) There's a lot wrong here:
847   // 1. We're not respecting verilog semantics (wrt sign and result)
848   // 2. This only works for single word inputs
849   // 3. We're not supporting reals, which this should be defined for
850 
851   assert(!lhs.is_real() && !rhs.is_real());
852   assert(size() == lhs.size());
853   assert(size() == rhs.size());
854   assert(val_.size() == 1);
855 
856   // No resize. This method preserves the bit-width of lhs
857   val_[0] = std::pow(lhs.val_[0], rhs.val_[0]);
858   trim();
859 }
860 
861 template <typename T, typename BT, typename ST>
logical_and(const BitsBase & lhs,const BitsBase & rhs)862 inline void BitsBase<T, BT, ST>::logical_and(const BitsBase& lhs, const BitsBase& rhs) {
863   assert(!is_real());
864   val_[0] = (lhs.to_bool() && rhs.to_bool()) ? static_cast<T>(1) : static_cast<T>(0);
865   trim();
866 }
867 
868 template <typename T, typename BT, typename ST>
logical_or(const BitsBase & lhs,const BitsBase & rhs)869 inline void BitsBase<T, BT, ST>::logical_or(const BitsBase& lhs, const BitsBase& rhs) {
870   assert(!is_real());
871   val_[0] = (lhs.to_bool() || rhs.to_bool()) ? static_cast<T>(1) : static_cast<T>(0);
872   trim();
873 }
874 
875 template <typename T, typename BT, typename ST>
logical_not(const BitsBase & lhs)876 inline void BitsBase<T, BT, ST>::logical_not(const BitsBase& lhs) {
877   assert(!is_real());
878   val_[0] = lhs.to_bool() ? static_cast<T>(0) : static_cast<T>(1);
879   trim();
880 }
881 
882 template <typename T, typename BT, typename ST>
logical_eq(const BitsBase & lhs,const BitsBase & rhs)883 inline void BitsBase<T, BT, ST>::logical_eq(const BitsBase& lhs, const BitsBase& rhs) {
884   assert(!is_real());
885   val_[0] = (lhs == rhs) ? static_cast<T>(1) : static_cast<T>(0);
886   trim();
887 }
888 
889 template <typename T, typename BT, typename ST>
logical_ne(const BitsBase & lhs,const BitsBase & rhs)890 inline void BitsBase<T, BT, ST>::logical_ne(const BitsBase& lhs, const BitsBase& rhs) {
891   assert(!is_real());
892   val_[0] = (lhs != rhs) ? static_cast<T>(1) : static_cast<T>(0);
893   trim();
894 }
895 
896 template <typename T, typename BT, typename ST>
logical_lt(const BitsBase & lhs,const BitsBase & rhs)897 inline void BitsBase<T, BT, ST>::logical_lt(const BitsBase& lhs, const BitsBase& rhs) {
898   assert(!is_real());
899   val_[0] = (lhs < rhs) ? static_cast<T>(1) : static_cast<T>(0);
900   trim();
901 }
902 
903 template <typename T, typename BT, typename ST>
logical_lte(const BitsBase & lhs,const BitsBase & rhs)904 inline void BitsBase<T, BT, ST>::logical_lte(const BitsBase& lhs, const BitsBase& rhs) {
905   assert(!is_real());
906   val_[0] = (lhs <= rhs) ? static_cast<T>(1) : static_cast<T>(0);
907   trim();
908 }
909 
910 template <typename T, typename BT, typename ST>
logical_gt(const BitsBase & lhs,const BitsBase & rhs)911 inline void BitsBase<T, BT, ST>::logical_gt(const BitsBase& lhs, const BitsBase& rhs) {
912   assert(!is_real());
913   val_[0] = (lhs > rhs) ? static_cast<T>(1) : static_cast<T>(0);
914   trim();
915 }
916 
917 template <typename T, typename BT, typename ST>
logical_gte(const BitsBase & lhs,const BitsBase & rhs)918 inline void BitsBase<T, BT, ST>::logical_gte(const BitsBase& lhs, const BitsBase& rhs){
919   assert(!is_real());
920   val_[0] = (lhs >= rhs) ? static_cast<T>(1) : static_cast<T>(0);
921   trim();
922 }
923 
924 template <typename T, typename BT, typename ST>
reduce_and(const BitsBase & lhs)925 inline void BitsBase<T, BT, ST>::reduce_and(const BitsBase& lhs) {
926   assert(!is_real() && !lhs.is_real());
927   // Logical operations always yield unsigned results
928   for (size_t i = 0, ie = lhs.val_.size()-1; i < ie; ++i) {
929     if (lhs.val_[i] != static_cast<T>(-1)) {
930       val_[0] = static_cast<T>(0);
931       trim();
932       return;
933     }
934   }
935   const auto mask = (static_cast<T>(1) << (size_ % bits_per_word())) - 1;
936   if ((lhs.val_.back() & mask) != mask) {
937     val_[0] = static_cast<T>(0);
938     trim();
939     return;
940   }
941   val_[0] = static_cast<T>(1);
942   trim();
943   return;
944 }
945 
946 template <typename T, typename BT, typename ST>
reduce_nand(const BitsBase & lhs)947 inline void BitsBase<T, BT, ST>::reduce_nand(const BitsBase& lhs) {
948   assert(!is_real() && !lhs.is_real());
949   reduce_and(lhs);
950   val_[0] = (val_[0] != 0) ? static_cast<T>(0) : static_cast<T>(1);
951 }
952 
953 template <typename T, typename BT, typename ST>
reduce_or(const BitsBase & lhs)954 inline void BitsBase<T, BT, ST>::reduce_or(const BitsBase& lhs) {
955   assert(!is_real() && !lhs.is_real());
956   for (size_t i = 0, ie = lhs.val_.size(); i < ie; ++i) {
957     if (lhs.val_[i]) {
958       val_[0] = static_cast<T>(1);
959       trim();
960       return;
961     }
962   }
963   val_[0] = static_cast<T>(0);
964   trim();
965 }
966 
967 template <typename T, typename BT, typename ST>
reduce_nor(const BitsBase & lhs)968 inline void BitsBase<T, BT, ST>::reduce_nor(const BitsBase& lhs) {
969   assert(!is_real() && !lhs.is_real());
970   reduce_or(lhs);
971   val_[0] = (val_[0] != 0) ? static_cast<T>(0) : static_cast<T>(1);
972 }
973 
974 template <typename T, typename BT, typename ST>
reduce_xor(const BitsBase & lhs)975 inline void BitsBase<T, BT, ST>::reduce_xor(const BitsBase& lhs) {
976   assert(!is_real() && !lhs.is_real());
977   size_t cnt = 0;
978   for (size_t i = 0, ie = lhs.val_.size(); i < ie; ++i) {
979     cnt += __builtin_popcount(lhs.val_[i]);
980   }
981   val_[0] = static_cast<T>(cnt % 2);
982   trim();
983 }
984 
985 template <typename T, typename BT, typename ST>
reduce_xnor(const BitsBase & lhs)986 inline void BitsBase<T, BT, ST>::reduce_xnor(const BitsBase& lhs) {
987   assert(!is_real() && !lhs.is_real());
988   reduce_xor(lhs);
989   val_[0] = (val_[0] != 0) ? static_cast<T>(0) : static_cast<T>(1);
990 }
991 
992 template <typename T, typename BT, typename ST>
concat(const BitsBase & rhs)993 inline void BitsBase<T, BT, ST>::concat(const BitsBase& rhs) {
994   assert(!is_real() && !rhs.is_real());
995 
996   bitwise_sll_const(*this, rhs.size_);
997   for (size_t i = 0, ie = std::min(val_.size(), rhs.val_.size()); i < ie; ++i) {
998     val_[i] |= rhs.val_[i];
999   }
1000 }
1001 
1002 template <typename T, typename BT, typename ST>
eq(const BitsBase & rhs)1003 inline bool BitsBase<T, BT, ST>::eq(const BitsBase& rhs) const {
1004   if (is_real() && rhs.is_real()) {
1005     return *reinterpret_cast<const double*>(val_.data()) == *reinterpret_cast<const double*>(rhs.val_.data());
1006   }
1007   if (is_real()) {
1008     auto temp = *this;
1009     temp.cast_type(Type::SIGNED);
1010     return temp.eq(rhs);
1011   }
1012   if (rhs.is_real()) {
1013     auto temp = rhs;
1014     temp.cast_type(Type::SIGNED);
1015     return eq(temp);
1016   }
1017 
1018   size_t i = 0;
1019   for (size_t ie = val_.size()-1; i < ie; ++i) {
1020     const auto rval = rhs.signed_get(i);
1021     if (val_[i] != rval) {
1022       return false;
1023     }
1024   }
1025   const auto rval = rhs.signed_get(i);
1026   const auto lover = size_ % bits_per_word();
1027   if (lover == 0) {
1028     return val_[i] == rval;
1029   } else {
1030     const auto mask = (static_cast<T>(1) << lover) - 1;
1031     return val_[i] == (rval & mask);
1032   }
1033 }
1034 
1035 template <typename T, typename BT, typename ST>
eq(size_t idx,const BitsBase & rhs)1036 inline bool BitsBase<T, BT, ST>::eq(size_t idx, const BitsBase& rhs) const {
1037   assert(!is_real());
1038   if (rhs.is_real()) {
1039     auto temp = rhs;
1040     temp.cast_type(Type::SIGNED);
1041     return eq(idx, temp);
1042   }
1043 
1044   assert(idx < size_);
1045   return get(idx) == rhs.get(0);
1046 }
1047 
1048 template <typename T, typename BT, typename ST>
eq(size_t msb,size_t lsb,const BitsBase & rhs)1049 inline bool BitsBase<T, BT, ST>::eq(size_t msb, size_t lsb, const BitsBase& rhs) const {
1050   assert(!is_real());
1051   if (rhs.is_real()) {
1052     auto temp = rhs;
1053     temp.cast_type(Type::SIGNED);
1054     return eq(msb, lsb, temp);
1055   }
1056 
1057   // Corner Case: Is this a single bit range?
1058   if (msb == lsb) {
1059     return eq(msb, rhs);
1060   }
1061 
1062   assert(msb < size_);
1063   assert(msb >= lsb);
1064 
1065   // Compute the size of this slice
1066   const auto slice = (msb - lsb) + 1;
1067   // How many full words does it span and what's left over at the end?
1068   const auto span = slice / bits_per_word();
1069   const auto lover = slice % bits_per_word();
1070   // Compute indices and offsets
1071   const auto lower = lsb / bits_per_word();
1072   const auto loff = lsb % bits_per_word();
1073   const auto uoff = bits_per_word() - loff;
1074 
1075   // Common Case: Full word comparison
1076   for (size_t i = 0; i < span; ++i) {
1077     auto word = (val_[lower+i] >> loff);
1078     const auto rval = rhs.signed_get(i);
1079     if (loff > 0) {
1080       word |= (val_[lower+i+1] << uoff);
1081     }
1082     if (word != rval) {
1083       return false;
1084     }
1085   }
1086 
1087   // Nothing to do if there are no leftovers:
1088   if (lover == 0) {
1089     return true;
1090   }
1091   // Edge Case: Compare the remaining bits
1092   auto word = (val_[lower+span] >> loff);
1093   const auto rval = rhs.signed_get(span);
1094   if ((loff > 0) && ((lower+span+1) < val_.size())) {
1095     word |= (val_[lower+span+1] << uoff);
1096   }
1097   const auto mask = (static_cast<T>(1) << lover) - 1;
1098   return (word & mask) == (rval & mask);
1099 }
1100 
1101 template <typename T, typename BT, typename ST>
assign(const BitsBase & rhs)1102 inline void BitsBase<T, BT, ST>::assign(const BitsBase& rhs) {
1103   if (is_real()) {
1104     const auto val = rhs.is_real() ? *reinterpret_cast<const double*>(rhs.val_.data()) : rhs.to_double();
1105     *reinterpret_cast<double*>(val_.data()) = val;
1106     return;
1107   }
1108   if (rhs.is_real()) {
1109     auto temp = rhs;
1110     temp.cast_real_to_int(false);
1111     return assign(temp);
1112   }
1113 
1114   assert(!is_real() && !rhs.is_real());
1115   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
1116     val_[i] = rhs.signed_get(i);
1117   }
1118   trim();
1119 }
1120 
1121 template <typename T, typename BT, typename ST>
assign(size_t idx,const BitsBase & rhs)1122 inline void BitsBase<T, BT, ST>::assign(size_t idx, const BitsBase& rhs) {
1123   assert(!is_real());
1124   assert(idx < size_);
1125   set(idx, rhs.to_uint() & static_cast<T>(1));
1126 }
1127 
1128 template <typename T, typename BT, typename ST>
assign(size_t msb,size_t lsb,const BitsBase & rhs)1129 inline void BitsBase<T, BT, ST>::assign(size_t msb, size_t lsb, const BitsBase& rhs) {
1130   // Corner Case: Is this range one bit?
1131   if (msb == lsb) {
1132     return assign(msb, rhs);
1133   }
1134   // Corner Case: Do we need to convert rhs to an integer?
1135   if (rhs.is_real()) {
1136     auto temp = rhs;
1137     temp.cast_real_to_int(false);
1138     return assign(msb, lsb, temp);
1139   }
1140 
1141   assert(!is_real() && !rhs.is_real());
1142   assert(msb < size_);
1143   assert(msb >= lsb);
1144 
1145   // Compute the size of this slice
1146   const auto slice = (msb - lsb) + 1;
1147   // How many full words does it span and what's left over at the end?
1148   const auto span = slice / bits_per_word();
1149   const auto lover = slice % bits_per_word();
1150   // Compute indices and offsets
1151   const auto lower = lsb / bits_per_word();
1152   const auto loff = lsb % bits_per_word();
1153   const auto uoff = bits_per_word() - loff;
1154   const auto mask = (static_cast<T>(1) << loff) - 1;
1155 
1156   // Common Case: Copy entire words
1157   for (size_t i = 0; i < span; ++i) {
1158     const auto rval = rhs.signed_get(i);
1159     val_[lower+i] &= mask;
1160     val_[lower+i] |= (rval << loff);
1161     if (loff > 0) {
1162       val_[lower+i+1] &= ~mask;
1163       val_[lower+i+1] |= (rval >> uoff);
1164     }
1165   }
1166 
1167   // Nothing to do if there are no leftovers
1168   if (lover == 0) {
1169     return;
1170   }
1171   // Edge Case: Copy the remaining bits
1172   const auto lmask = (static_cast<T>(1) << lover) - 1;
1173   const auto rval = rhs.signed_get(span);
1174   val_[lower+span] &= ~(lmask << loff);
1175   val_[lower+span] |= ((rval & lmask) << loff);
1176 
1177   if ((lover + loff) > bits_per_word()) {
1178     const auto delta = (lover + loff) - bits_per_word();
1179     const auto hmask = (static_cast<T>(1) << delta) - 1;
1180     val_[lower+span+1] &= ~hmask;
1181     val_[lower+span+1] |= ((rval >> (lover-delta)) & hmask);
1182   }
1183 }
1184 
1185 template <typename T, typename BT, typename ST>
assign(const BitsBase & rhs,size_t idx)1186 inline void BitsBase<T, BT, ST>::assign(const BitsBase& rhs, size_t idx) {
1187   assert(!is_real() && !rhs.is_real());
1188 
1189   val_[0] = (idx < rhs.size()) ? rhs.get(idx) : static_cast<T>(0);
1190   for (size_t i = 1, ie = val_.size(); i < ie; ++i) {
1191     val_[i] = static_cast<T>(0);
1192   }
1193 }
1194 
1195 template <typename T, typename BT, typename ST>
assign(const BitsBase & rhs,size_t msb,size_t lsb)1196 inline void BitsBase<T, BT, ST>::assign(const BitsBase& rhs, size_t msb, size_t lsb) {
1197   assert(!is_real() && !rhs.is_real());
1198 
1199   // Corner Case: Is this range 1 bit?
1200   if (msb == lsb) {
1201     return assign(rhs, msb);
1202   }
1203 
1204   assert(msb < rhs.size_);
1205   assert(msb >= lsb);
1206 
1207   // How many words does this slice span? Where does it start?
1208   const auto span = ((msb-lsb)+bits_per_word()) / bits_per_word();
1209   const auto base = lsb / bits_per_word();
1210   const auto bamt = lsb % bits_per_word();
1211   // Create a mask for extracting the lowest bamt bits from top
1212   const auto mamt = bits_per_word() - bamt;
1213   const auto mask = (static_cast<T>(1) << bamt) - 1;
1214 
1215   // Copy as much of rhs as we can (maybe along with a few bits extra)
1216   size_t i = 0;
1217   for (size_t ie = std::min(span, val_.size()); i < ie; ++i) {
1218     if (bamt == 0) {
1219       val_[i] = rhs.val_[base+i];
1220     } else {
1221       const auto top = ((base+i+1) < rhs.val_.size()) ? rhs.val_[base+i+1] : static_cast<T>(0);
1222       val_[i] = ((top & mask) << mamt) | (rhs.val_[base+i] >> bamt);
1223     }
1224   }
1225 
1226   // Zero out anything which is left over
1227   const auto top = std::min(static_cast<uint32_t>((msb-lsb)+1), size_);
1228   const auto zword = top / bits_per_word();
1229   const auto zidx = top % bits_per_word();
1230 
1231   if (zword < val_.size()) {
1232     val_[zword] &= (static_cast<T>(1) << zidx) - 1;
1233   }
1234   for (size_t i = zword+1, ie = val_.size(); i < ie; ++i) {
1235     val_[i] = static_cast<T>(0);
1236   }
1237 }
1238 
1239 template <typename T, typename BT, typename ST>
copy(const BitsBase & rhs)1240 inline void BitsBase<T, BT, ST>::copy(const BitsBase& rhs) {
1241   val_.resize(rhs.val_.size());
1242   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
1243     val_[i] = rhs.val_[i];
1244   }
1245   size_ = rhs.size_;
1246   type_ = rhs.type_;
1247 }
1248 
1249 template <typename T, typename BT, typename ST>
get(size_t idx)1250 inline bool BitsBase<T, BT, ST>::get(size_t idx) const {
1251   assert(idx < size_);
1252 
1253   const auto widx = idx / bits_per_word();
1254   const auto bidx = idx % bits_per_word();
1255   return val_[widx] & (static_cast<T>(1) << bidx);
1256 }
1257 
1258 template <typename T, typename BT, typename ST>
set(size_t idx,bool b)1259 inline void BitsBase<T, BT, ST>::set(size_t idx, bool b) {
1260   assert(idx < size_);
1261 
1262   const auto widx = idx / bits_per_word();
1263   const auto bidx = idx % bits_per_word();
1264   if (b) {
1265     val_[widx] |= (static_cast<T>(1) << bidx);
1266   } else {
1267     val_[widx] &= ~(static_cast<T>(1) << bidx);
1268   }
1269 }
1270 
1271 template <typename T, typename BT, typename ST>
flip(size_t idx)1272 inline void BitsBase<T, BT, ST>::flip(size_t idx) {
1273   assert(idx < size_);
1274 
1275   const auto widx = idx / bits_per_word();
1276   const auto bidx = idx % bits_per_word();
1277   const bool b = (val_[widx] >> bidx) & static_cast<T>(1);
1278   if (!b) {
1279     val_[widx] |= (static_cast<T>(1) << bidx);
1280   } else {
1281     val_[widx] &= ~(static_cast<T>(1) << bidx);
1282   }
1283 }
1284 
1285 template <typename T, typename BT, typename ST>
1286 inline bool BitsBase<T, BT, ST>::operator==(const BitsBase& rhs) const {
1287   if (is_real() && rhs.is_real()) {
1288     return *reinterpret_cast<const double*>(val_.data()) == *reinterpret_cast<const double*>(rhs.val_.data());
1289   }
1290   if (is_real()) {
1291     auto temp = *this;
1292     temp.cast_type(Type::SIGNED);
1293     temp.resize(rhs.size_);
1294     return temp == rhs;
1295   }
1296   if (rhs.is_real()) {
1297     auto temp = rhs;
1298     temp.cast_type(Type::SIGNED);
1299     temp.resize(size_);
1300     return *this == temp;
1301   }
1302 
1303   assert(size_ == rhs.size_);
1304   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
1305     if (val_[i] != rhs.val_[i]) {
1306       return false;
1307     }
1308   }
1309   return true;
1310 }
1311 
1312 template <typename T, typename BT, typename ST>
1313 inline bool BitsBase<T, BT, ST>::operator!=(const BitsBase& rhs) const {
1314   return !(*this == rhs);
1315 }
1316 
1317 template <typename T, typename BT, typename ST>
1318 inline bool BitsBase<T, BT, ST>::operator<(const BitsBase& rhs) const {
1319   if (is_real() && rhs.is_real()) {
1320     return *reinterpret_cast<const double*>(val_.data()) < *reinterpret_cast<const double*>(rhs.val_.data());
1321   }
1322   if (is_real()) {
1323     auto temp = *this;
1324     temp.cast_type(Type::SIGNED);
1325     temp.resize(rhs.size_);
1326     return temp < rhs;
1327   }
1328   if (rhs.is_real()) {
1329     auto temp = rhs;
1330     temp.cast_type(Type::SIGNED);
1331     temp.resize(size_);
1332     return *this < temp;
1333   }
1334 
1335   assert(size_ == rhs.size_);
1336   if ((type_ == Type::SIGNED) && (rhs.type_ == Type::SIGNED)) {
1337     const auto lneg = is_neg_signed();
1338     const auto rneg = rhs.is_neg_signed();
1339     if (lneg && !rneg) {
1340       return true;
1341     } else if (!lneg && rneg) {
1342       return false;
1343     }
1344   }
1345   for (int i = val_.size()-1; i >= 0; --i) {
1346     if (val_[i] < rhs.val_[i]) {
1347       return true;
1348     } else if (val_[i] > rhs.val_[i]) {
1349       return false;
1350     }
1351   }
1352   return false;
1353 }
1354 
1355 template <typename T, typename BT, typename ST>
1356 inline bool BitsBase<T, BT, ST>::operator<=(const BitsBase& rhs) const {
1357   if (is_real() && rhs.is_real()) {
1358     return *reinterpret_cast<const double*>(val_.data()) <= *reinterpret_cast<const double*>(rhs.val_.data());
1359   }
1360   if (is_real()) {
1361     auto temp = *this;
1362     temp.cast_type(Type::SIGNED);
1363     temp.resize(rhs.size_);
1364     return temp <= rhs;
1365   }
1366   if (rhs.is_real()) {
1367     auto temp = rhs;
1368     temp.cast_type(Type::SIGNED);
1369     temp.resize(size_);
1370     return *this <= temp;
1371   }
1372 
1373   assert(size_ == rhs.size_);
1374   if ((type_ == Type::SIGNED) && (rhs.type_ == Type::SIGNED)) {
1375     const auto lneg = is_neg_signed();
1376     const auto rneg = rhs.is_neg_signed();
1377     if (lneg && !rneg) {
1378       return true;
1379     } else if (!lneg && rneg) {
1380       return false;
1381     }
1382   }
1383 
1384   for (int i = val_.size()-1; i >= 0; --i) {
1385     if (val_[i] < rhs.val_[i]) {
1386       return true;
1387     } else if (val_[i] > rhs.val_[i]) {
1388       return false;
1389     }
1390   }
1391   return true;
1392 }
1393 
1394 template <typename T, typename BT, typename ST>
1395 inline bool BitsBase<T, BT, ST>::operator>(const BitsBase& rhs) const {
1396   return !(*this <= rhs);
1397 }
1398 
1399 template <typename T, typename BT, typename ST>
1400 inline bool BitsBase<T, BT, ST>::operator>=(const BitsBase& rhs) const {
1401   return !(*this < rhs);
1402 }
1403 
1404 template <typename T, typename BT, typename ST>
read_real(std::istream & is)1405 inline void BitsBase<T, BT, ST>::read_real(std::istream& is) {
1406   double d;
1407   is >> d;
1408   val_.resize(64/bits_per_word());
1409   *reinterpret_cast<double*>(val_.data()) = d;
1410   size_ = 64;
1411   type_ = Type::REAL;
1412 }
1413 
1414 template <typename T, typename BT, typename ST>
read_2_8_16(std::istream & is,size_t base)1415 inline void BitsBase<T, BT, ST>::read_2_8_16(std::istream& is, size_t base) {
1416   // Input Buffer:
1417   std::string s;
1418   is >> s;
1419 
1420   // Reset to a 1-bit unsigned value
1421   shrink_to_bool(false);
1422   type_ = Type::UNSIGNED;
1423 
1424   // Return immediately if reading s failed.
1425   if (s.empty()) {
1426     return;
1427   }
1428 
1429   // How many bits do we generate per character? Resize internal storage.
1430   const auto step = (base == 2) ? 1 : (base == 8) ? 3 : 4;
1431   extend_to(step * s.length());
1432 
1433   // Walk over the buffer from lowest to highest order (that's in reverse)
1434   size_t word = 0;
1435   size_t idx = 0;
1436   for (int i = s.length()-1; i >= 0; --i) {
1437     // Convert character to bits
1438     const T bits = static_cast<bool>(isalpha(s[i])) ? ((s[i]-'a')+10) : (s[i]-'0');
1439     // Copy bits into storage and bump idx.
1440     val_[word] |= (bits << idx);
1441     idx += step;
1442     // Keep going if there's still room in this word, otherwise on to the next
1443     if (idx < bits_per_word()) {
1444       continue;
1445     }
1446     ++word;
1447     // Easy Case: Step divides words evenly
1448     if (idx == bits_per_word()) {
1449       idx = 0;
1450       continue;
1451     }
1452     // Hard Case: Bit overflow
1453     idx -= bits_per_word();
1454     val_[word] |= (bits >> (step-idx));
1455   }
1456 }
1457 
1458 template <typename T, typename BT, typename ST>
read_10(std::istream & is)1459 inline void BitsBase<T, BT, ST>::read_10(std::istream& is) {
1460   // Check for negative
1461   const auto is_neg = is.peek() == '-';
1462   if (is_neg) {
1463     is.get();
1464   }
1465 
1466   // Input Buffer:
1467   std::string s;
1468   is >> s;
1469 
1470   // Reset to 1-bit signed value
1471   shrink_to_bool(false);
1472   type_ = is_neg ? Type::SIGNED : Type::UNSIGNED;
1473 
1474   // Halve decimal string until it becomes zero. Add 1s when least significant
1475   // digit is odd, 0s otherwise. An empty string will leave this loop
1476   // immediately.
1477   for (size_t i = 1; !dec_zero(s); ++i) {
1478     extend_to(i);
1479     set(i-1, (s.back()-'0') % 2);
1480     dec_halve(s);
1481   }
1482   // Add padding for sign bit and negate if necessary
1483   extend_to(size_+1);
1484   if (is_neg) {
1485     invert_add_one();
1486   }
1487 }
1488 
1489 template <typename T, typename BT, typename ST>
write_real(std::ostream & os)1490 inline void BitsBase<T, BT, ST>::write_real(std::ostream& os) const {
1491   os << to_double();
1492 }
1493 
1494 template <typename T, typename BT, typename ST>
write_2_8_16(std::ostream & os,size_t base)1495 inline void BitsBase<T, BT, ST>::write_2_8_16(std::ostream& os, size_t base) const {
1496   // Cast to unsigned
1497   if (type_ != Type::UNSIGNED) {
1498     auto temp = *this;
1499     temp.cast_type(Type::UNSIGNED);
1500     return temp.write_2_8_16(os, base);
1501   }
1502 
1503   // TODO(eschkufz): This would be a lot faster if we traversed the value from
1504   // most to least significant bit and didn't store a temporary array.
1505 
1506   // Output Buffer:
1507   std::vector<uint8_t> buf;
1508 
1509   // How many bits do we consume per character? Make a mask.
1510   const size_t step = (base == 2) ? 1 : (base == 8) ? 3 : 4;
1511   const auto mask = (static_cast<T>(1) << step) - 1;
1512 
1513   // Walk over the string from lowest to highest order
1514   size_t off = 0;
1515   for (size_t i = 0, ie = size(); i < ie; i += step) {
1516     const auto pos = i / bits_per_word();
1517     // Extract mask bits
1518     buf.push_back((val_[pos] >> off) & mask);
1519     off += step;
1520     // Easy case: Step divides words evenly
1521     if (off == bits_per_word()) {
1522       off = 0;
1523     }
1524     // Hard case: Look ahead for more bits
1525     else if (off > bits_per_word()) {
1526       off %= bits_per_word();
1527       if ((pos+1) != val_.size()) {
1528         buf.back() |= (val_[pos+1] & ((static_cast<T>(1) << off) - 1)) << (step - off);
1529       }
1530     }
1531   }
1532 
1533   // Print the result
1534   for (int i = buf.size()-1; i >= 0; --i) {
1535     if (buf[i] > 9) {
1536       os << static_cast<char>('a' + (buf[i] - 10));
1537     } else {
1538       os << static_cast<int>(buf[i]);
1539     }
1540   }
1541 }
1542 
1543 
1544 template <typename T, typename BT, typename ST>
write_10(std::ostream & os)1545 inline void BitsBase<T, BT, ST>::write_10(std::ostream& os) const {
1546   // Cast reals down to integers
1547   if (type_ == Type::REAL) {
1548     auto temp = *this;
1549     temp.cast_type(Type::SIGNED);
1550     return temp.write_10(os);
1551   }
1552 
1553   // Check whether this is a negative number
1554   const auto is_neg = is_neg_signed();
1555 
1556   // Print negative and invert if necessary
1557   if (is_neg) {
1558     os << "-";
1559     const_cast<BitsBase*>(this)->invert_add_one();
1560   }
1561   // Output Buffer (lsb in index 0):
1562   std::string buf = "0";
1563   // Walk binary string from highest to lowest.
1564   // Double result each time, add 1s as they appear.
1565   for (int i = size_-1; i >= 0; --i) {
1566     dec_double(buf);
1567     if (get(i)) {
1568       dec_inc(buf);
1569     }
1570   }
1571   // Print the result in reverse
1572   for (int i = buf.length()-1; i >= 0; --i) {
1573     os << buf[i];
1574   }
1575   // Restore bits if they were inverted
1576   if (is_neg) {
1577     const_cast<BitsBase*>(this)->invert_add_one();
1578   }
1579 }
1580 
1581 template <typename T, typename BT, typename ST>
dec_halve(std::string & s)1582 inline void BitsBase<T, BT, ST>::dec_halve(std::string& s) const {
1583   auto next_carry = 0;
1584   for (size_t i = 0, ie = s.length(); i < ie; ++i) {
1585     const auto val = s[i] - '0';
1586     auto carry = next_carry;
1587     next_carry = ((val % 2) != 0) ? 5 : 0;
1588     s[i] = ((val/2) + carry) + '0';
1589   }
1590 }
1591 
1592 template <typename T, typename BT, typename ST>
dec_zero(const std::string & s)1593 inline bool BitsBase<T, BT, ST>::dec_zero(const std::string& s) const {
1594   for (auto c : s) {
1595     if (c != '0') {
1596       return false;
1597     }
1598   }
1599   return true;
1600 }
1601 
1602 template <typename T, typename BT, typename ST>
dec_double(std::string & s)1603 inline void BitsBase<T, BT, ST>::dec_double(std::string& s) const {
1604   auto carry = 0;
1605   for (size_t i = 0, ie = s.size(); i < ie; ++i) {
1606     auto val = s[i] - '0';
1607     val = (2*val) + carry;
1608     if (val >= 10) {
1609       s[i] = '0' + (val - 10);
1610       carry = 1;
1611     } else {
1612       s[i] = '0' + val;
1613       carry = 0;
1614     }
1615   }
1616   if (carry) {
1617     s.push_back('1');
1618   }
1619 }
1620 
1621 template <typename T, typename BT, typename ST>
dec_inc(std::string & s)1622 inline void BitsBase<T, BT, ST>::dec_inc(std::string& s) const {
1623   for (size_t i = 0, ie = s.size(); i < ie; ++i) {
1624     if (++s[i] == ('0'+10)) {
1625       s[i] = '0';
1626     } else {
1627       return;
1628     }
1629   }
1630   s.push_back('1');
1631 }
1632 
1633 template <typename T, typename BT, typename ST>
bitwise_sll_const(const BitsBase & lhs,size_t samt)1634 inline void BitsBase<T, BT, ST>::bitwise_sll_const(const BitsBase& lhs, size_t samt) {
1635   assert(!is_real() && !lhs.is_real());
1636   assert(size() == lhs.size());
1637 
1638   // Easy Case: We're not actually shifting
1639   if (samt == 0) {
1640     for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
1641       val_[i] = lhs.val_[i];
1642     }
1643     return;
1644   }
1645 
1646   // This algorithm works from highest to lowest order, one word at a time
1647   // word: The current word we're looking at
1648   // top/bottom: The words that will be shifted into word; word can equal top
1649 
1650   // How many words ahead is bottom?
1651   const auto delta = ((samt + bits_per_word()) - 1) / bits_per_word();
1652   // How many bits are we taking from bottom and shifting top?
1653   const auto bamt = samt % bits_per_word();
1654   // Create a mask for extracting the highest bamt bits from bottom
1655   const auto mamt = bits_per_word() - bamt;
1656   const auto mask = ((static_cast<T>(1) << bamt) - 1) << mamt;
1657 
1658   // Work our way down until bottom hits zero
1659   int w = val_.size() - 1;
1660   for (int b = w-delta; b >= 0; --w, --b) {
1661     if (bamt == 0) {
1662       val_[w] = lhs.val_[b];
1663     } else {
1664       val_[w] = (lhs.val_[b+1] << bamt) | ((lhs.val_[b] & mask) >> mamt);
1665     }
1666   }
1667   // There's one more block to build where bottom is implicitly zero
1668   val_[w--] = (bamt == 0) ? static_cast<T>(0) : (lhs.val_[0] << bamt);
1669   // Everything else is zero
1670   for (; w >= 0; --w) {
1671     val_[w] = static_cast<T>(0);
1672   }
1673   // Trim the top and we're done
1674   trim();
1675 }
1676 
1677 template <typename T, typename BT, typename ST>
bitwise_sxr_const(const BitsBase & lhs,size_t samt,bool arith)1678 inline void BitsBase<T, BT, ST>::bitwise_sxr_const(const BitsBase& lhs, size_t samt, bool arith) {
1679   assert(!is_real() && !lhs.is_real());
1680   assert(size() == lhs.size());
1681 
1682   // Easy Case: We're not actually shifting
1683   if (samt == 0) {
1684     for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
1685       val_[i] = lhs.val_[i];
1686     }
1687     return;
1688   }
1689   // Another Easy Case: We're shifting more bits than we have here
1690   if (samt >= lhs.size()) {
1691     const auto val = (arith && lhs.get(lhs.size()-1)) ? T(-1) : T(0);
1692     for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
1693       val_[i] = val;
1694     }
1695     return;
1696   }
1697 
1698   // This algorithm works from lowest to highest order, one word at a time
1699   // word: The current word we're looking at
1700   // top/bottom: The words that will be shifted into word; word can equal bottom
1701 
1702   // Is the highest order bit a 1 and do we care?
1703   const auto idx = (size_-1) % bits_per_word();
1704   const auto hob = arith && ((lhs.val_.back() & (static_cast<T>(1) << idx)) != 0);
1705   // How many words ahead is top?
1706   const auto delta = ((samt + bits_per_word()) - 1) / bits_per_word();
1707   // How many bits are we taking from top and shifting bottom?
1708   const auto bamt = samt % bits_per_word();
1709   // Create a mask for extracting the lowest bamt bits from top
1710   const auto mamt = bits_per_word() - bamt;
1711   const auto mask = (static_cast<T>(1) << bamt) - 1;
1712   // val_ is an array of unsigned values. If we are working with signed values,
1713   // we want the top bits of the top-most word to be filled with ones.
1714   // This is only used in the case where hob is set and the top word is not
1715   // completely full.
1716   const auto upper_most_word = ((static_cast<T>(-1) << idx) | lhs.val_.back());
1717 
1718   // Work our way up until top goes out of range
1719   size_t w = 0;
1720   for (size_t t = w+delta, te = val_.size(); t < te; ++w, ++t) {
1721     if (bamt == 0) {
1722       val_[w] = lhs.val_[t];
1723     } else {
1724       const auto upper_most = (t == (val_.size() - 1)) ? upper_most_word : lhs.val_[t];
1725       val_[w] = (lhs.val_[t-1] >> bamt) | ((upper_most & mask) << mamt);
1726     }
1727   }
1728   // There's one more block to build where top is implicitly zero
1729   if (hob) {
1730     val_[w++] = (bamt == 0) ? static_cast<T>(-1) : ((upper_most_word >> bamt) | (mask << mamt));
1731   } else {
1732     val_[w++] = (bamt == 0) ? static_cast<T>(0) : (lhs.val_.back() >> bamt);
1733   }
1734   // Everything else is zero or padded 1s
1735   for (size_t we = val_.size(); w < we; ++w) {
1736     val_[w] = hob ? static_cast<T>(-1) : static_cast<T>(0);
1737   }
1738   // Trim since we could have introduced trailing 1s
1739   trim();
1740 }
1741 
1742 template <typename T, typename BT, typename ST>
signed_get(size_t n)1743 inline T BitsBase<T, BT, ST>::signed_get(size_t n) const {
1744   // Easiest Case: This is an unisgned value, so return what's in range or zero
1745   if (!is_neg_signed()) {
1746     return (n < val_.size()) ? val_[n] : static_cast<T>(0);
1747   }
1748   // Another Case: An in bounds signed value
1749   else if (n < (val_.size()-1)) {
1750     return val_[n];
1751   }
1752   // One More Easy Case: An out of bounds signed value
1753   else if (n >= val_.size()) {
1754     return static_cast<T>(-1);
1755   }
1756   // The Hard Case: We need to sign extend
1757   else {
1758     const auto top = size_ % bits_per_word();
1759     return (top == 0) ? val_[n] : (val_[n] | (static_cast<T>(-1) << top));
1760   }
1761 }
1762 
1763 template <typename T, typename BT, typename ST>
is_neg_signed()1764 inline bool BitsBase<T, BT, ST>::is_neg_signed() const {
1765   return (type_ == Type::SIGNED) && get(size_-1);
1766 }
1767 
1768 template <typename T, typename BT, typename ST>
trim()1769 inline void BitsBase<T, BT, ST>::trim() {
1770   // How many bits do we care about in the top word?
1771   const auto trailing = size_ % bits_per_word();
1772   // Zero means we're full
1773   if (trailing == 0) {
1774     return;
1775   }
1776   // Otherwise, mask these off
1777   const auto mask = (static_cast<T>(1) << trailing) - 1;
1778   val_.back() &= mask;
1779 }
1780 
1781 template <typename T, typename BT, typename ST>
extend_to(size_t n)1782 inline void BitsBase<T, BT, ST>::extend_to(size_t n) {
1783   assert(n >= size_);
1784   const auto words = ((n + bits_per_word()) - 1) / bits_per_word();
1785   val_.resize(words, static_cast<T>(0));
1786   size_ = n;
1787 }
1788 
1789 template <typename T, typename BT, typename ST>
sign_extend_to(size_t n)1790 inline void BitsBase<T, BT, ST>::sign_extend_to(size_t n) {
1791   assert(n >= size_);
1792   const auto words = ((n + bits_per_word()) - 1) / bits_per_word();
1793   if (is_neg_signed()) {
1794     val_.back() |= (static_cast<T>(-1) << (size_ % bits_per_word()));
1795     val_.resize(words, static_cast<T>(-1));
1796     size_ = n;
1797     trim();
1798   } else {
1799     val_.resize(words, static_cast<T>(0));
1800     size_ = n;
1801   }
1802 }
1803 
1804 template <typename T, typename BT, typename ST>
shrink_to(size_t n)1805 inline void BitsBase<T, BT, ST>::shrink_to(size_t n) {
1806   assert(n <= size_);
1807   const auto words = ((n + bits_per_word()) - 1) / bits_per_word();
1808   val_.resize(words, static_cast<T>(0));
1809   size_ = n;
1810   trim();
1811 }
1812 
1813 template <typename T, typename BT, typename ST>
shrink_to_bool(bool b)1814 inline void BitsBase<T, BT, ST>::shrink_to_bool(bool b) {
1815   val_.resize(1, static_cast<T>(0));
1816   val_[0] = b ? 1 : 0;
1817   size_ = 1;
1818 }
1819 
1820 template <typename T, typename BT, typename ST>
invert_add_one()1821 inline void BitsBase<T, BT, ST>::invert_add_one() {
1822   T carry = 1;
1823   for (size_t i = 0, ie = val_.size(); i < ie; ++i) {
1824     val_[i] = ~val_[i];
1825     const T sum = val_[i] + carry;
1826     carry = (sum < val_[i]) ? static_cast<T>(1) : static_cast<T>(0);
1827     val_[i] = sum;
1828   }
1829   trim();
1830 }
1831 
1832 template <typename T, typename BT, typename ST>
cast_int_to_real()1833 inline void BitsBase<T, BT, ST>::cast_int_to_real() {
1834   assert(type_ != Type::REAL);
1835   const auto d = to_double();
1836   val_.resize(64/bits_per_word());
1837   *reinterpret_cast<double*>(val_.data()) = d;
1838   size_ = 64;
1839   type_ = Type::REAL;
1840 }
1841 
1842 template <typename T, typename BT, typename ST>
cast_real_to_int(bool s)1843 inline void BitsBase<T, BT, ST>::cast_real_to_int(bool s) {
1844   assert(type_ == Type::REAL);
1845   auto d = std::round(*reinterpret_cast<const double*>(val_.data()));
1846   const auto is_neg = d < 0.0;
1847   if (is_neg) {
1848     d = -d;
1849   }
1850 
1851   shrink_to_bool(false);
1852   for (size_t i = 1; d > 0; d = std::floor(d/2), ++i) {
1853     extend_to(i);
1854     set(i-1, static_cast<T>(d) % 2);
1855   }
1856   if (s) {
1857     extend_to(size_+1);
1858   }
1859   if (is_neg) {
1860     invert_add_one();
1861   }
1862   type_ = s ? Type::SIGNED : Type::UNSIGNED;
1863 }
1864 
1865 template <typename T, typename BT, typename ST>
bits_per_word()1866 inline constexpr size_t BitsBase<T, BT, ST>::bits_per_word() const {
1867   return 8 * bytes_per_word();
1868 }
1869 
1870 template <typename T, typename BT, typename ST>
bytes_per_word()1871 inline constexpr size_t BitsBase<T, BT, ST>::bytes_per_word() const {
1872   return sizeof(T);
1873 }
1874 
1875 template <typename T, typename BT, typename ST>
range()1876 inline constexpr double BitsBase<T, BT, ST>::range() const {
1877   return std::pow(2, bits_per_word());
1878 }
1879 
1880 } // namespace cascade
1881 
1882 #endif
1883