1 #pragma once 2 // bitblock.hpp : bitblock class 3 // 4 // Copyright (C) 2017-2018 Stillwater Supercomputing, Inc. 5 // 6 // This file is part of the universal numbers project, which is released under an MIT Open Source license. 7 8 #include <sstream> 9 10 // this should be removed when we have made the transition away from std::bitset to sw::unum::bitblock 11 #include <cassert> 12 #include "ubb.h" 13 14 15 namespace sw { namespace universal { 16 17 /** 18 @brief templated class implementing efficient multi-precision binary arithmetic and logic 19 */ 20 template<size_t nbits> 21 class bitblock : public universal_bitset::bitset<nbits> { 22 public: bitblock()23 bitblock() { 24 setzero(); 25 } 26 27 bitblock(const bitblock&) = default; 28 bitblock(bitblock&&) = default; 29 bitblock& operator=(const bitblock&) = default; 30 bitblock& operator=(bitblock&&) = default; 31 32 // assignment operators for native types operator =(signed char rhs)33 bitblock& operator=(signed char rhs) { universal_bitset::bitset<nbits>::operator=(rhs); return *this; } operator =(short rhs)34 bitblock& operator=(short rhs) { universal_bitset::bitset<nbits>::operator=(rhs); return *this; } operator =(int rhs)35 bitblock& operator=(int rhs) { universal_bitset::bitset<nbits>::operator=(rhs); return *this; } operator =(long rhs)36 bitblock& operator=(long rhs) { universal_bitset::bitset<nbits>::operator=(rhs); return *this; } operator =(long long rhs)37 bitblock& operator=(long long rhs) { universal_bitset::bitset<nbits>::operator=(rhs); return *this; } operator =(char rhs)38 bitblock& operator=(char rhs) { universal_bitset::bitset<nbits>::operator=(rhs); return *this; } operator =(unsigned short rhs)39 bitblock& operator=(unsigned short rhs) {universal_bitset::bitset<nbits>::operator=(rhs); return *this; } operator =(unsigned int rhs)40 bitblock& operator=(unsigned int rhs) { universal_bitset::bitset<nbits>::operator=(rhs); return *this; } operator =(unsigned long rhs)41 bitblock& operator=(unsigned long rhs) { universal_bitset::bitset<nbits>::operator=(rhs); return *this; } operator =(unsigned long long rhs)42 bitblock& operator=(unsigned long long rhs) { universal_bitset::bitset<nbits>::operator=(rhs); return *this; } 43 to_ullong() const44 unsigned long long to_ullong() const { 45 return this->M_do_to_ullong(); 46 } 47 setzero()48 void setzero() { 49 universal_bitset::bitset<nbits>::reset(); 50 } 51 load_bits(const std::string & string_of_bits)52 bool load_bits(const std::string& string_of_bits) { 53 if (string_of_bits.length() != nbits) 54 return false; 55 56 setzero(); 57 int msb = nbits - 1; 58 59 for (std::string::const_iterator it = string_of_bits.begin(); it != string_of_bits.end(); ++it) { 60 61 if (*it == '0') { 62 this->reset(msb--); 63 } 64 else if (*it == '1') { 65 this->set(msb--); 66 } 67 else { 68 return false; 69 } 70 } 71 return true; 72 } 73 }; 74 75 /** 76 @param val is a bitblock value. 77 78 @return value of sign bit. 79 */ 80 template<size_t nbits> getSignBit(const bitblock<nbits> & val)81 unsigned int getSignBit(const bitblock<nbits>& val) { 82 return val[nbits - 1]; 83 } 84 85 // logic operators: unsigned (in)equality inherited. 86 87 // this comparison is for a two's complement number only 88 template<size_t nbits> lessThan(const bitblock<nbits> & lhs,const bitblock<nbits> & rhs)89 bool lessThan(const bitblock<nbits>& lhs, 90 const bitblock<nbits>& rhs) { 91 // Short-circuits on disparate signs: 92 if (getSignBit(lhs) == 0 && getSignBit(rhs) == 1) { 93 return false; 94 } 95 if (getSignBit(lhs) == 1 && getSignBit(rhs) == 0) { 96 return true; 97 } 98 99 // Sign bits agree, can compare bit patterns directly: 100 return lhs < rhs; 101 } 102 103 /** 104 @brief Vestigial alias for '<' operator: unsigned. 105 */ 106 template<size_t nbits> lessThan_unsigned(const bitblock<nbits> & lhs,const bitblock<nbits> & rhs)107 bool lessThan_unsigned(const bitblock<nbits> &lhs, 108 const bitblock<nbits> &rhs) { 109 return lhs < rhs; 110 } 111 112 ////////////////////////////// ARITHMETIC functions 113 ////////////////////////////////////////////////////////////////////////////////////// 114 // increment and decrement 115 116 /** 117 @brief Increments value in place. 118 119 @param[in, out] number is the value to decrement. 120 121 @return true iff the sign has changed from nonnegative to negative. 122 */ 123 template<size_t nbits> increment_bitset(bitblock<nbits> & number)124 bool increment_bitset(bitblock<nbits>& number) { 125 unsigned int signPre = getSignBit(number); 126 number.increment(); 127 unsigned int signPost = getSignBit(number); 128 return signPost > signPre; 129 } 130 131 // increment the input bitset in place, and return true if there is a carry generated. 132 // The input number is assumed to be right adjusted starting at nbits-nrBits 133 // [1 0 0 0] nrBits = 0 is a noop as there is no word to increment 134 // [1 0 0 0] nrBits = 1 is the word [1] 135 // [1 0 0 0] nrBits = 2 is the word [1 0] 136 // [1 1 0 0] nrBits = 3 is the word [1 1 0], etc. 137 138 template<size_t nbits> increment_unsigned(bitblock<nbits> & number,int nrBits=nbits-1)139 bool increment_unsigned(bitblock<nbits>& number, int nrBits = nbits - 1) { 140 bool carry = 1; // ripple carry 141 int lsb = nbits - nrBits; 142 for (size_t i = lsb; i < nbits; i++) { 143 bool _a = number[i]; 144 number[i] = _a ^ carry; 145 carry = (_a & false) | (carry & (_a ^ false)); 146 } 147 return carry; 148 } 149 150 151 /** 152 @brief Decrements value in place. 153 154 @param[in, out] number is the value to decrement. 155 156 @return true iff the sign has changed from negative to nonnegative. 157 */ 158 template<size_t nbits> decrement_bitset(bitblock<nbits> & number)159 bool decrement_bitset(bitblock<nbits>& number) { 160 unsigned int signPre = getSignBit(number); 161 (void)number.decrement(); 162 unsigned int signPost = getSignBit(number); 163 return signPost < signPre; 164 } 165 166 167 ////////////////////////////////////////////////////////////////////////////////////// 168 169 /** 170 @brief Adds two nbit summands into nbit+1 result. 171 172 @param a is an addend. 173 174 @param b is an addend. 175 176 @param[out] sum contains the sum, with carry bit set. 177 178 @return true iff carry precipitated. 179 */ 180 template<size_t nbits> add_unsigned(const bitblock<nbits> & a,const bitblock<nbits> & b,bitblock<nbits+1> & sum)181 bool add_unsigned(const bitblock<nbits> &a, 182 const bitblock<nbits> &b, 183 bitblock<nbits + 1>& sum) { 184 return sum.add(a, b); 185 } 186 187 // subtract bitsets a and b and return result in bitset dif. Return true if there is a borrow generated. 188 template<size_t nbits> subtract_unsigned(bitblock<nbits> a,bitblock<nbits> b,bitblock<nbits+1> & dif)189 bool subtract_unsigned(bitblock<nbits> a, 190 bitblock<nbits> b, 191 bitblock<nbits + 1>& dif) { 192 return dif.sub(a, b); 193 } 194 195 template<size_t nbits> add_signed_magnitude(bitblock<nbits> a,bitblock<nbits> b,bitblock<nbits> & sum)196 bool add_signed_magnitude(bitblock<nbits> a, 197 bitblock<nbits> b, 198 bitblock<nbits>& sum) { 199 uint8_t carry = 0; 200 bool sign_a = a.test(nbits - 1); 201 if (sign_a) { 202 a = a.flip(); 203 carry += 1; 204 } 205 bool sign_b = b.test(nbits - 1); 206 if (sign_b) { 207 b = b.flip(); 208 carry += 1; 209 } 210 for (int i = 0; i < nbits - 2; i++) { 211 bool _a = a[i]; 212 bool _b = b[i]; 213 sum[i] = _a ^ _b ^ carry; 214 carry = (_a & _b) | (carry & (_a ^ _b)); 215 } 216 217 return carry; 218 } 219 220 221 template<size_t nbits> subtract_signed_magnitude(bitblock<nbits> a,bitblock<nbits> b,bitblock<nbits> & diff)222 bool subtract_signed_magnitude(bitblock<nbits> a, 223 bitblock<nbits> b, 224 bitblock<nbits>& diff) { 225 bool sign_a = a.test(nbits - 1); 226 bool sign_b = b.test(nbits - 1); 227 std::cerr << "subtract_signed_magnitude not implemented yet" << std::endl; 228 return false; 229 } 230 231 232 // integral type to bitblock transformations 233 // we are using a full nbits sized bitset even though nbits-3 is the maximum fraction 234 // a posit would contain. However, we need an extra bit after the cut-off to make the 235 // round up/down decision. The <nbits-something> size created a lot of sw complexity 236 // that isn't worth the trouble, so we are simplifying and simply manage a full nbits 237 // of fraction bits. 238 239 template<size_t nbits> extract_23b_fraction(uint32_t _23b_fraction_without_hidden_bit)240 bitblock<nbits> extract_23b_fraction(uint32_t _23b_fraction_without_hidden_bit) { 241 bitblock<nbits> _fraction; 242 uint32_t mask = uint32_t(0x00400000ul); 243 unsigned int ub = (nbits < 23 ? nbits : 23); 244 for (unsigned int i = 0; i < ub; i++) { 245 _fraction[nbits - 1 - i] = _23b_fraction_without_hidden_bit & mask; 246 mask >>= 1; 247 } 248 return _fraction; 249 } 250 251 template<size_t nbits> extract_52b_fraction(uint64_t _52b_fraction_without_hidden_bit)252 bitblock<nbits> extract_52b_fraction(uint64_t _52b_fraction_without_hidden_bit) { 253 bitblock<nbits> _fraction; 254 uint64_t mask = uint64_t(0x0008000000000000ull); 255 unsigned int ub = (nbits < 52 ? nbits : 52); 256 for (unsigned int i = 0; i < ub; i++) { 257 _fraction[nbits - 1 - i] = _52b_fraction_without_hidden_bit & mask; 258 mask >>= 1; 259 } 260 return _fraction; 261 } 262 263 264 template<size_t nbits> extract_63b_fraction(uint64_t _63b_fraction_without_hidden_bit)265 bitblock<nbits> extract_63b_fraction(uint64_t _63b_fraction_without_hidden_bit) { 266 bitblock<nbits> _fraction; 267 uint64_t mask = uint64_t(0x4000000000000000ull); 268 unsigned int ub = (nbits < 63 ? nbits : 63); 269 for (unsigned int i = 0; i < ub; i++) { 270 _fraction[nbits - 1 - i] = _63b_fraction_without_hidden_bit & mask; 271 mask >>= 1; 272 } 273 return _fraction; 274 } 275 276 // 128 bit unsigned int mapped to two uint64_t elements 277 typedef struct __uint128 { 278 uint64_t lower; 279 uint64_t upper; 280 } uint128; 281 282 283 // take in a long double mapped to two uint64_t elements 284 template<size_t nbits> extract_long_double_fraction(uint128 * _112b_fraction_without_hidden_bit)285 bitblock<nbits> extract_long_double_fraction(uint128* _112b_fraction_without_hidden_bit) { 286 bitblock<nbits> _fraction; 287 int msb = nbits - 1; 288 uint64_t mask = uint64_t(0x0000800000000000ull); 289 unsigned int ub = (nbits < 48 ? nbits : 48); // 48 bits in the upper half 290 for (unsigned int i = 0; i < ub; i++) { 291 _fraction[msb--] = _112b_fraction_without_hidden_bit->upper & mask; 292 mask >>= 1; 293 } 294 mask = uint64_t(0x8000000000000000ull); 295 ub = (nbits < 112 - 48 ? nbits : 112 - 48); // max 64 bits in the lower half 296 for (unsigned int i = 0; i < ub; i++) { 297 _fraction[msb--] = _112b_fraction_without_hidden_bit->lower & mask; 298 mask >>= 1; 299 } 300 return _fraction; 301 } 302 303 template<size_t nbits> copy_integer_fraction(unsigned long long _fraction_without_hidden_bit)304 bitblock<nbits> copy_integer_fraction(unsigned long long _fraction_without_hidden_bit) { 305 bitblock<nbits> _fraction; 306 uint64_t mask = uint64_t(0x8000000000000000ull); 307 unsigned int ub = (nbits < 64 ? nbits : 64); 308 for (unsigned int i = 0; i < ub; i++) { 309 _fraction[nbits - 1 - i] = _fraction_without_hidden_bit & mask; 310 mask >>= 1; 311 } 312 return _fraction; 313 } 314 315 316 //////////////////////////////////////////////////////////////////////////////////////// 317 // bitset copy and slice operators 318 319 // copy a bitset into a bigger bitset starting at position indicated by the shift value 320 template<size_t src_size, size_t tgt_size> copy_into(const bitblock<src_size> & src,size_t shift,bitblock<tgt_size> & tgt)321 void copy_into(const bitblock<src_size>& src, size_t shift, bitblock<tgt_size>& tgt) { 322 tgt.reset(); 323 for (size_t i = 0; i < src_size; i++) 324 tgt.set(i + shift, src[i]); 325 } 326 327 328 // copy a slice of a bitset into a bigger bitset starting at position indicated by the shift value 329 template<size_t src_size, size_t tgt_size> copy_slice_into(bitblock<src_size> & src,bitblock<tgt_size> & tgt,size_t begin=0,size_t end=src_size,size_t shift=0)330 void copy_slice_into(bitblock<src_size>& src, bitblock<tgt_size>& tgt, size_t begin = 0, size_t end = src_size, size_t shift = 0) { 331 // do NOT reset the target!!! 332 if (end <= src_size) throw iteration_bound_too_large{}; 333 if (end + shift < tgt_size) throw iteration_bound_too_large{}; 334 for (size_t i = begin; i < end; i++) 335 tgt.set(i + shift, src[i]); 336 } 337 338 template<size_t from, size_t to, size_t src_size> fixed_subset(const bitblock<src_size> & src)339 bitblock<to - from> fixed_subset(const bitblock<src_size>& src) { 340 static_assert(from <= to, "from cannot be larger than to"); 341 static_assert(to <= src_size, "to is larger than src_size"); 342 343 bitblock<to - from> result; 344 for (size_t i = 0, end = to - from; i < end; ++i) 345 result[i] = src[i + from]; 346 347 return result; 348 } 349 350 ////////////////////////////////////////////////////////////////////////////////////// 351 // multiply and divide 352 353 354 // multiply bitsets a and b and return result in bitset result. 355 template<size_t operand_size> multiply_unsigned(const bitblock<operand_size> & a,const bitblock<operand_size> & b,bitblock<2* operand_size> & result)356 void multiply_unsigned(const bitblock<operand_size>& a, const bitblock<operand_size>& b, bitblock<2 * operand_size>& result) { 357 constexpr size_t result_size = 2 * operand_size; 358 bitblock<result_size> addend; 359 result.reset(); 360 if (a.test(0)) { 361 copy_into<operand_size, result_size>(b, 0, result); 362 } 363 for (size_t i = 1; i < operand_size; i++) { 364 if (a.test(i)) { 365 copy_into<operand_size, result_size>(b, i, addend); 366 (void)result.add(addend); 367 // we should never have a carry: assert(carry == false); 368 } 369 } 370 } 371 372 373 // divide bitsets a and b and return result in bitset result. 374 template<size_t operand_size> integer_divide_unsigned(const bitblock<operand_size> & a,const bitblock<operand_size> & b,bitblock<2* operand_size> & result)375 void integer_divide_unsigned(const bitblock<operand_size>& a, 376 const bitblock<operand_size>& b, 377 bitblock<2 * operand_size>& result) { 378 bitblock<operand_size> subtractand, accumulator; 379 result.reset(); 380 accumulator = a; 381 int msb = findMostSignificantBit(b); 382 if (msb < 0) { 383 throw integer_divide_by_zero{}; 384 } 385 386 const unsigned int shift = operand_size - msb - 1; 387 // prepare the subtractand 388 subtractand = b; 389 subtractand <<= shift; 390 for (int i = shift; i >= 0; --i) { 391 if (subtractand <= accumulator) { 392 (void)accumulator.sub(subtractand); 393 result.set(i); 394 } 395 else { 396 result.reset(i); 397 } 398 subtractand >>= 1; 399 } 400 } 401 402 403 // divide bitsets a and b and return result in bitset result. 404 // By providing more bits in the result, the algorithm will fill these with fraction bits if available. 405 // Radix point must be maintained by calling function. 406 template<size_t operand_size, size_t result_size> divide_with_fraction(const bitblock<operand_size> & a,const bitblock<operand_size> & b,bitblock<result_size> & result)407 void divide_with_fraction(const bitblock<operand_size>& a, 408 const bitblock<operand_size>& b, 409 bitblock<result_size>& result) { 410 bitblock<result_size> subtractand, accumulator; 411 result.reset(); 412 copy_into<operand_size, result_size>(a, result_size - operand_size, accumulator); 413 int msb = findMostSignificantBit(b); 414 if (msb < 0) { 415 throw integer_divide_by_zero{}; 416 } 417 418 int shift = operand_size - msb - 1; 419 // prepare the subtractand 420 copy_into<operand_size, result_size>(b, result_size - operand_size, subtractand); 421 subtractand <<= shift; 422 for (int i = result_size - msb - 1; i >= 0; --i) { 423 //std::cout << "accumulator " << accumulator << std::endl; 424 //std::cout << "subtractand " << subtractand << std::endl; 425 if (subtractand <= accumulator) { 426 (void)accumulator.sub(subtractand); 427 //assert(borrow == false); 428 result.set(i); 429 } 430 else { 431 result.reset(i); 432 } 433 //std::cout << "result " << result << std::endl; 434 subtractand >>= 1; 435 } 436 } 437 438 ////////////////////////////////////////////////////////////////////////////////////// 439 // truncating and rounding 440 441 // truncate right-side 442 template<size_t src_size, size_t tgt_size> truncate(bitblock<src_size> & src,bitblock<tgt_size> & tgt)443 void truncate(bitblock<src_size>& src, bitblock<tgt_size>& tgt) { 444 tgt.reset(); 445 for (size_t i = 0; i < tgt_size; i++) 446 tgt.set(tgt_size - 1 - i, src[src_size - 1 - i]); 447 } 448 449 450 // round 451 template<size_t tgt_size, size_t src_size> 452 struct round_t 453 { evalsw::universal::round_t454 static bitblock<tgt_size> eval(const bitblock<src_size>& src, size_t n) 455 { 456 static_assert(src_size > 0 && tgt_size > 0, "We don't bother with empty sets."); 457 if (n >= src_size) 458 throw round_off_all{}; 459 460 // look for cut-off leading bits 461 for (size_t leading = tgt_size + n; leading < src_size; ++leading) 462 if (src[leading]) 463 throw cut_off_leading_bit{}; 464 465 bitblock<tgt_size> result((src >> n).to_ullong()); // convert to size_t to deal with different sizes 466 if (n > 0 && src[n - 1]) { // round up potentially if first cut-off bit is true 467 # ifdef POSIT_ROUND_TIES_AWAY_FROM_ZERO // TODO: Evil hack to be consistent with assign_fraction, for testing only 468 result = result.to_ullong() + 1; 469 # else 470 471 bool more_bits = false; 472 for (long i = 0; i + 1 < n && !more_bits; ++i) 473 more_bits |= src[i]; 474 if (more_bits) { 475 result = result.to_ullong() + 1; // increment_unsigned is ambiguous 476 } 477 else { // tie: round up odd number 478 # ifndef POSIT_ROUND_TIES_TO_ZERO // TODO: evil hack to be removed later 479 if (result[0]) 480 result = result.to_ullong() + 1; 481 # endif 482 } 483 # endif 484 485 } 486 return result; 487 } 488 }; 489 490 template<size_t src_size> 491 struct round_t<0, src_size> 492 { evalsw::universal::round_t493 static bitblock<0> eval(const bitblock<src_size>&, size_t) 494 { 495 return {}; 496 } 497 }; 498 499 500 501 /** Round off \p n last bits of bitset \p src. Round to nearest resulting in potentially smaller bitset. 502 * Doesn't return carry bit in case of overflow while rounding up! TODO: Check whether we need carry or we require an extra bit for this case. 503 */ 504 template<size_t tgt_size, size_t src_size> round(const bitblock<src_size> & src,size_t n)505 bitblock<tgt_size> round(const bitblock<src_size>& src, size_t n) 506 { 507 return round_t<tgt_size, src_size>::eval(src, n); 508 } 509 510 511 ////////////////////////////// HELPER functions 512 513 // Attention! 514 // Achtung! 515 // Regardez! 516 // Waarschuwing! 517 // DANGER: this depends on the implicit type conversion of number 518 // to a uint64_t for sign-extending a 2's complement number system. 519 // If nbits > 64 then this code breaks. 520 template<size_t nbits, class Type> convert_to_bitblock(Type number)521 bitblock<nbits> convert_to_bitblock(Type number) { 522 bitblock<nbits> bBits; 523 const uint64_t one = uint64_t(1); 524 for (std::size_t i = 0; i < nbits; i++) { 525 bBits[i] = (one << i) & number; 526 } 527 528 return bBits; 529 } 530 531 /** 532 @brief Constructs a string of 1's and 0's representing the 533 value passed. 534 535 @param bit contains the value to display. 536 537 @return string representing the value. 538 */ 539 template<size_t nbits> to_binary(bitblock<nbits> const & bits)540 std::string to_binary(bitblock<nbits> const &bits) { 541 char str[nbits + 1]; 542 str[nbits] = 0; 543 for (size_t i = 0; i < nbits; i++) { 544 str[nbits - 1 - i] = bits[i] ? '1' : '0'; 545 } 546 return std::string(str); 547 } 548 549 template<size_t nbits> to_hex(bitblock<nbits> bits)550 std::string to_hex(bitblock<nbits> bits) { 551 char str[(nbits >> 2) + 2]; // plenty of room 552 for (size_t i = 0; i < (nbits >> 2) + 2; ++i) str[i] = 0; 553 const char* hexits = "0123456789ABCDEF"; 554 unsigned int maxHexDigits = (nbits >> 2) + ((nbits % 4) ? 1 : 0); 555 for (unsigned int i = 0; i < maxHexDigits; i++) { 556 unsigned int hexit; 557 switch (nbits) { 558 case 1: 559 hexit = bits[0]; 560 break; 561 case 2: 562 hexit = (bits[1] << 1) + bits[0]; 563 break; 564 case 3: 565 hexit = (bits[2] << 2) + (bits[1] << 1) + bits[0]; 566 break; 567 default: 568 hexit = (bits[3] << 3) + (bits[2] << 2) + (bits[1] << 1) + bits[0]; 569 break; 570 } 571 str[maxHexDigits - 1 - i] = hexits[hexit]; 572 bits >>= 4; 573 } 574 str[maxHexDigits] = 0; // null terminated string 575 return std::string(str); 576 } 577 578 // convert a sign/magnitude number to a string 579 template<size_t nbits> sign_magnitude_to_string(bitblock<nbits> bits)580 std::string sign_magnitude_to_string(bitblock<nbits> bits) { 581 std::stringstream ss; 582 ss << (bits[nbits - 1] ? "n-" : "p-"); 583 if (nbits < 2) return ss.str(); 584 for (int i = nbits - 2; i >= 0; --i) { 585 ss << (bits[i] ? "1" : "0"); 586 } 587 return ss.str(); 588 } 589 590 591 // find the MSB, return position if found, return -1 if no bits are set 592 template<size_t nbits> findMostSignificantBit(const bitblock<nbits> & bits)593 int findMostSignificantBit(const bitblock<nbits>& bits) { 594 return bits.getMSB(); 595 } 596 597 // calculate the 1's complement of a sign-magnitude encoded number 598 599 template<size_t nbits> ones_complement(const bitblock<nbits> & number)600 bitblock<nbits> ones_complement(const bitblock<nbits> &number) { 601 bitblock<nbits> complement = number; 602 complement.flip(); 603 return complement; 604 } 605 606 607 // calculate the 2's complement of a 2's complement encoded number 608 template<size_t nbits> twos_complement(const bitblock<nbits> & number)609 bitblock<nbits> twos_complement(const bitblock<nbits> &number) { 610 bitblock<nbits> complement; 611 uint8_t carry = 1; 612 for (size_t i = 0; i < nbits; i++) { 613 uint8_t slice = uint8_t(!number[i]) + carry; 614 carry = slice >> 1; 615 complement[i] = (0x1 & slice); 616 } 617 618 return complement; 619 } 620 621 622 /** 623 @brief Flips the sign bit of value passed. 624 625 @param number is a value for which the sign is to be flipped. 626 627 @return new bitset with the sign flipped as compared to number 628 */ 629 template<size_t nbits> flip_sign_bit(const bitblock<nbits> & number)630 bitblock<nbits> flip_sign_bit(const bitblock<nbits> &number) { 631 bitblock<nbits> negate = number; 632 negate.flip(nbits - 1); 633 return negate; 634 } 635 636 /** 637 @return true iff any bit at or right of msb is set. 638 */ 639 template<size_t nbits> anyAfter(const bitblock<nbits> & bits,unsigned msb)640 bool anyAfter(const bitblock<nbits>& bits, unsigned msb) { 641 bitblock<nbits> shBits = bits; 642 shBits <<= (nbits - 1 - msb); 643 return shBits.count() > 0; 644 } 645 646 }} // namespace sw::universal 647