38 template <
unsigned W2>
42 template <
unsigned W2>
44 { copy_from<W2>(rhs, 0); }
53 unsigned msb()
const {
54 for (
unsigned w = W-1 ; w < UINT_MAX ; --w) {
55 if (
m_data[w] == 0)
continue;
56 for (
unsigned b = 31 ; b < 32 ; --b) {
57 if (
m_data[w] & (1u << b))
return 32*w+b;
71 for (
unsigned a = 0 ; a+1 < W ; ++a) {
79 for (
unsigned a = 0 ; a+1 < W ; ++a) {
80 if (
m_data[a] != UINT32_MAX)
break;
98 for (
unsigned a = 0 ; a < W ; ++a) {
111 explicit operator bool()
const {
113 for (
unsigned a = 0 ; a < W ; ++a) {
118 explicit constexpr
operator int32_t()
const {
119 return (int32_t)uint32_t(*
this);
121 explicit constexpr
operator int64_t()
const {
122 return (int64_t)uint64_t(*
this);
124 explicit constexpr
operator uint32_t()
const {
125 return (W > 0) ?
m_data[0] : 0;
127 explicit constexpr
operator uint64_t()
const {
128 return u64((W > 1) ?
m_data[1] : 0) << 32
129 | u64((W > 0) ?
m_data[0] : 0);
136 for (
unsigned a = W-1 ; a < UINT_MAX ; --a) {
145 for (
unsigned a = W-1 ; a < UINT_MAX ; --a) {
146 m_data[a] = rd->read_u32();
156 for (
unsigned a = W-1 ; a < UINT_MAX ; --a) {
172 :
m_data{u32(rhs >> 0), u32(rhs >> 32)} {}
179 for (
unsigned a = 1 ; a < W ; ++a)
184 :
m_data{u32(rhs >> 0), u32(rhs >> 32)}
186 for (
unsigned a = 2 ; a < W ; ++a)
191 template <
typename T>
static inline constexpr u32
sign_extend(T x)
192 {
return u32((x < 0) ? -1 : 0); }
194 template <
unsigned W2>
196 for (
unsigned a = 0 ; a < W ; ++a) {
204 WideInteger<W> add(
const WideInteger<W>& rhs)
const {
207 for (
unsigned a = 0 ; a < W ; ++a) {
208 tmp.m_data[a] =
m_data[a] + rhs.m_data[a];
213 for (
unsigned a = 0 ; a+1 < W ; ++a) {
214 if (tmp.m_data[a] < rhs.m_data[a]) {
215 ++tmp.m_data[a+1]; carry =
true;
216 }
else if (carry && tmp.m_data[a] == rhs.m_data[a]) {
217 ++tmp.m_data[a+1]; carry =
true;
225 void add_in_place(
const WideInteger<W>& rhs) {
227 for (
unsigned a = 0 ; a < W ; ++a) {
228 m_data[a] += rhs.m_data[a];
233 for (
unsigned a = 0 ; a+1 < W ; ++a) {
234 if (
m_data[a] < rhs.m_data[a]) {
235 ++
m_data[a+1]; carry =
true;
236 }
else if (carry &&
m_data[a] == rhs.m_data[a]) {
237 ++
m_data[a+1]; carry =
true;
244 WideInteger<W> subtract(
const WideInteger<W>& rhs)
const {
247 for (
unsigned a = 0 ; a < W ; ++a) {
248 tmp.m_data[a] =
m_data[a] - rhs.m_data[a];
253 for (
unsigned a = 0 ; a+1 < W ; ++a) {
254 if (rhs.m_data[a] >
m_data[a]) {
255 --tmp.m_data[a+1]; carry =
true;
256 }
else if (carry && rhs.m_data[a] ==
m_data[a]) {
257 --tmp.m_data[a+1]; carry =
true;
265 WideInteger<W> multiply(
const WideInteger<W>& rhs)
const {
268 WideInteger<W> sum(u32(0));
269 for (
unsigned a = 0 ; a < W ; ++a) {
270 for (
unsigned b = 0 ; a + b < W ; ++b) {
272 u64 bb = (u64)rhs.m_data[b];
273 WideInteger<W> p(aa * bb);
274 unsigned scale = 32 * (a + b);
275 sum.add_in_place(p.shift_left(scale));
281 WideInteger<W> shift_left(
unsigned rhs)
const {
282 unsigned rw = rhs / 32;
283 unsigned rb = rhs % 32;
284 unsigned rc = 32 - rb;
286 for (
unsigned a = 0 ; a < W ; ++a) {
287 u32 hi = (a >= rw) ? (
m_data[a-rw] << rb) : 0;
288 u32 lo = (rb && a > rw) ? (
m_data[a-rw-1] >> rc) : 0;
289 tmp.m_data[a] = hi | lo;
294 WideInteger<W> shift_right(
unsigned rhs, u32 ext)
const {
295 unsigned rw = rhs / 32;
296 unsigned rb = rhs % 32;
297 unsigned rc = 32 - rb;
299 for (
unsigned a = 0 ; a < W ; ++a) {
300 u32 hi = (a+rw+1 < W) ?
m_data[a+rw+1] : ext;
301 u32 lo = (a+rw < W) ?
m_data[a+rw] : ext;
302 tmp.m_data[a] = rb ? ((hi << rc) | (lo >> rb)) : lo;
307 WideInteger<W> bitwise_invert()
const {
309 for (
unsigned a = 0 ; a < W ; ++a) {
310 tmp.m_data[a] = ~
m_data[a];
315 void bitwise_or(
const WideInteger<W>& rhs) {
316 for (
unsigned a = 0 ; a < W ; ++a) {
317 m_data[a] |= rhs.m_data[a];
321 void bitwise_and(
const WideInteger<W>& rhs) {
322 for (
unsigned a = 0 ; a < W ; ++a) {
323 m_data[a] &= rhs.m_data[a];
327 void bitwise_xor(
const WideInteger<W>& rhs) {
328 for (
unsigned a = 0 ; a < W ; ++a) {
329 m_data[a] ^= rhs.m_data[a];
354 { this->copy_from(rhs, 0); }
356 { this->copy_from(rhs, 0);
return *
this; }
361 return this->m_data[W-1] >= 0x80000000u;
372 if (*
this > limit_pos) *
this = limit_pos;
373 if (*
this < limit_neg) *
this = limit_neg;
382 {
return this->add(rhs); }
384 { this->add_in_place(rhs);
return *
this; }
386 {
return this->subtract(rhs); }
388 { *
this = this->subtract(rhs);
return *
this; }
390 {
return this->multiply(rhs); }
392 { *
this = this->multiply(rhs);
return *
this; }
398 { *
this = *
this / rhs;
return *
this; }
400 { *
this = *
this % rhs;
return *
this; }
402 {
return this->shift_left(rhs); }
404 { *
this = this->shift_left(rhs);
return *
this; }
406 {
return this->shift_right(rhs, this->
sign_extend()); }
408 { *
this = *
this >> rhs;
return *
this; }
410 {
return this->bitwise_invert(); }
412 { this->bitwise_or(rhs);
return *
this; }
414 { this->bitwise_and(rhs);
return *
this; }
416 { this->bitwise_xor(rhs);
return *
this; }
433 unum.
divmod(urhs, udiv, umod);
452 if (W == 0)
return false;
454 if ((s32)this->m_data[W-1] < (s32)rhs.
m_data[W-1])
return true;
455 if ((s32)this->m_data[W-1] > (s32)rhs.
m_data[W-1])
return false;
457 for (
unsigned a = W-2 ; a < UINT_MAX ; --a) {
458 if (this->m_data[a] < rhs.
m_data[a])
return true;
459 if (this->m_data[a] > rhs.
m_data[a])
return false;
464 if (W == 0)
return false;
466 if ((s32)this->m_data[W-1] > (s32)rhs.
m_data[W-1])
return true;
467 if ((s32)this->m_data[W-1] < (s32)rhs.
m_data[W-1])
return false;
469 for (
unsigned a = W-2 ; a < UINT_MAX ; --a) {
470 if (this->m_data[a] > rhs.
m_data[a])
return true;
471 if (this->m_data[a] < rhs.
m_data[a])
return false;
495 constexpr
explicit WideUnsigned<W>(u64 rhs)
500 { this->copy_from(rhs, 0); }
502 { this->copy_from(rhs, 0);
return *
this; }
510 {
return this->add(rhs); }
511 inline WideUnsigned<W>& operator+=(
const WideInteger<W>& rhs)
512 { this->add_in_place(rhs);
return *
this; }
513 inline WideUnsigned<W>
operator-(
const WideInteger<W>& rhs)
const
514 {
return this->subtract(rhs); }
515 inline WideUnsigned<W>& operator-=(
const WideInteger<W>& rhs)
516 { *
this = this->subtract(rhs);
return *
this; }
517 inline WideUnsigned<W> operator*(
const WideInteger<W>& rhs)
const
518 {
return this->multiply(rhs); }
519 inline WideUnsigned<W>& operator*=(
const WideInteger<W>& rhs)
520 { *
this = this->multiply(rhs);
return *
this; }
521 inline WideUnsigned<W> operator/(
const WideUnsigned<W>& rhs)
const
522 { WideUnsigned<W> d, m; this->
divmod(rhs, d, m);
return d; }
523 inline WideUnsigned<W> operator%(
const WideUnsigned<W>& rhs)
const
524 { WideUnsigned<W> d, m; this->
divmod(rhs, d, m);
return m; }
525 inline WideUnsigned<W>& operator/=(
const WideInteger<W>& rhs)
526 { *
this = *
this / rhs;
return *
this; }
527 inline WideUnsigned<W>& operator%=(
const WideInteger<W>& rhs)
528 { *
this = *
this % rhs;
return *
this; }
529 inline WideUnsigned<W> operator<<(
unsigned rhs)
const
530 {
return this->shift_left(rhs); }
531 inline WideUnsigned<W> operator<<=(
unsigned rhs)
532 { *
this = this->shift_left(rhs);
return *
this; }
533 inline WideUnsigned<W> operator>>(
unsigned rhs)
const
534 {
return this->shift_right(rhs, 0); }
535 inline WideUnsigned<W> operator>>=(
unsigned rhs)
536 { *
this = *
this >> rhs;
return *
this; }
537 inline WideUnsigned<W> operator~()
const
538 {
return this->bitwise_invert(); }
539 inline WideUnsigned<W>& operator|=(
const WideInteger<W>& rhs)
540 { this->bitwise_or(rhs);
return *
this; }
541 inline WideUnsigned<W>& operator&=(
const WideInteger<W>& rhs)
542 { this->bitwise_and(rhs);
return *
this; }
543 inline WideUnsigned<W>& operator^=(
const WideInteger<W>& rhs)
544 { this->bitwise_xor(rhs);
return *
this; }
545 inline WideUnsigned<W> operator|(
const WideInteger<W>& rhs)
const
546 { WideInteger<W> tmp(*
this); tmp.bitwise_or(rhs);
return tmp; }
547 inline WideUnsigned<W> operator&(
const WideInteger<W>& rhs)
const
548 { WideInteger<W> tmp(*
this); tmp.bitwise_and(rhs);
return tmp; }
549 inline WideUnsigned<W> operator^(
const WideInteger<W>& rhs)
const
550 { WideInteger<W> tmp(*
this); tmp.bitwise_xor(rhs);
return tmp; }
551 inline WideUnsigned<W> div_round(
const WideUnsigned<W>& rhs)
const
552 {
return (*
this + (rhs >> 1)) / rhs; }
561 if (rhs <= ONE) {div = *
this; mod = ZERO;
return;}
562 if (*
this == rhs) {div = ONE; mod = ZERO;
return;}
563 if (*
this < rhs) {div = ZERO; mod = *
this;
return;}
565 unsigned msb = 1 + this->
msb() - rhs.
msb();
567 mod = *
this; div = ZERO;
568 for (
unsigned b =
msb ; b < UINT_MAX ; --b) {
571 div.
m_data[b/32] |= (1u << (b%32));
580 for (
unsigned a = W-1 ; a < UINT_MAX ; --a) {
581 if (this->m_data[a] < rhs.
m_data[a])
return true;
582 if (this->m_data[a] > rhs.
m_data[a])
return false;
587 for (
unsigned a = W-1 ; a < UINT_MAX ; --a) {
588 if (this->m_data[a] > rhs.
m_data[a])
return true;
589 if (this->m_data[a] < rhs.
m_data[a])
return false;
Abstract API for reading byte-streams and packets.
virtual unsigned get_read_ready() const =0
How many bytes can be read without blocking?
Abstract API for writing byte-streams and packets.
Internal buffer used by the Log class.
void wr_h32(u32 val, unsigned nhex=8)
Write an integer (u32) in hexadecimal format.
void wr_str(const char *str)
Write a null-terminated UTF-8 string.
I/O interface core definitions.
Diagnostic logging to UART and/or Ethernet ports.
Wide-integer parent class.
bool operator==(const WideInteger< W > &rhs) const
Equality comparison only.
bool read_from(satcat5::io::Readable *rd)
Read binary data from a given source.
unsigned width_bits() const
Total width in bits.
WideInteger< W > operator--(int)
Increment/decrement.
bool operator!=(const WideInteger< W > &rhs) const
Equality comparison only.
WideInteger< W > operator++(int)
Increment/decrement.
WideInteger< W > & operator++()
Increment/decrement.
void write_to(satcat5::io::Writeable *wr) const
Write binary data from a given sink.
WideInteger()=default
Constructors are private to force use of child classes.
u32 m_data[W]
Underlying data vector, LSW-first.
unsigned width_words() const
Total width in 32-bit words.
void log_to(satcat5::log::LogBuffer &obj) const
Human-readable logging in hexadecimal format.
WideInteger(const satcat5::util::WideSigned< W2 > &rhs)
Implicit size-converting copy constructors must know if the input is signed or unsigned to proceed.
WideInteger(const satcat5::util::WideUnsigned< W2 > &rhs)
Implicit size-converting copy constructors must know if the input is signed or unsigned to proceed.
unsigned msb() const
Index of most significant '1' bit.
WideInteger< W > & operator--()
Increment/decrement.
constexpr u32 sign_extend() const
Extend most significant word with either "0" or "FFFF...".
Template for signed integers.
WideSigned< W > operator+(const WideInteger< W > &rhs) const
Common arithmetic operators.
WideSigned< W > operator~() const
Common arithmetic operators.
WideSigned(const satcat5::util::WideInteger< W > &rhs)
Constructors for various input formats.
WideSigned(s64 rhs)
Constructors for various input formats.
WideSigned< W > operator/(const WideSigned< W > &rhs) const
Common arithmetic operators.
WideSigned< W > & operator^=(const WideInteger< W > &rhs)
Common arithmetic operators.
WideSigned< W > & operator|=(const WideInteger< W > &rhs)
Common arithmetic operators.
WideSigned< W > operator-(const WideInteger< W > &rhs) const
Common arithmetic operators.
bool is_negative() const
Is this integer negative, i.e., x < 0?
WideSigned< W > operator%(const WideSigned< W > &rhs) const
Common arithmetic operators.
bool operator<(const WideSigned< W > &rhs) const
Comparison operators.
constexpr WideSigned(u32 hi, u32 lo)
Constructors for various input formats.
WideSigned< W > operator&(const WideInteger< W > &rhs) const
Common arithmetic operators.
void divmod(const WideSigned< W > &rhs, WideSigned< W > &div, WideSigned< W > &mod) const
Combined divide + modulo function.
bool operator>(const WideSigned< W > &rhs) const
Comparison operators.
void clamp(const WideSigned< W > &limit_pos)
Clamp input to +/- limit_pos.
constexpr WideSigned(u32 rhs)
Constructors for various input formats.
satcat5::util::WideSigned< W > abs() const
Absolute value.
WideSigned< W > div_round(const WideSigned< W > &rhs) const
Divide and round toward zero.
WideSigned< W > operator*(const WideInteger< W > &rhs) const
Common arithmetic operators.
WideSigned< W > operator>>=(unsigned rhs)
Common arithmetic operators.
WideSigned< W > & operator%=(const WideInteger< W > &rhs)
Common arithmetic operators.
WideSigned< W > operator>>(unsigned rhs) const
Common arithmetic operators.
WideSigned< W > & operator*=(const WideInteger< W > &rhs)
Common arithmetic operators.
WideSigned< W > operator<<(unsigned rhs) const
Common arithmetic operators.
constexpr WideSigned()
Constructors for various input formats.
WideSigned< W > operator^(const WideInteger< W > &rhs) const
Common arithmetic operators.
constexpr WideSigned(u64 rhs)
Constructors for various input formats.
WideSigned< W > & operator=(const WideInteger< W > &rhs)
Constructors for various input formats.
WideSigned< W > operator<<=(unsigned rhs)
Common arithmetic operators.
WideSigned< W > & operator-=(const WideInteger< W > &rhs)
Common arithmetic operators.
bool operator>=(const WideSigned< W > &rhs) const
Comparison operators.
WideSigned< W > & operator&=(const WideInteger< W > &rhs)
Common arithmetic operators.
bool operator<=(const WideSigned< W > &rhs) const
Comparison operators.
WideSigned< W > & operator+=(const WideInteger< W > &rhs)
Common arithmetic operators.
WideSigned< W > operator|(const WideInteger< W > &rhs) const
Common arithmetic operators.
WideSigned< W > & operator/=(const WideInteger< W > &rhs)
Common arithmetic operators.
WideSigned< W > operator-() const
Common arithmetic operators.
WideSigned(s32 rhs)
Constructors for various input formats.
Template for unsigned integers.
void divmod(const WideUnsigned< W > &rhs, WideUnsigned< W > &div, WideUnsigned< W > &mod) const
Combined divide + modulo function.
WideUnsigned(const satcat5::util::WideInteger< W > &rhs)
Constructors for various input formats.
WideUnsigned< W > operator-() const
Common arithmetic operators.
bool operator>(const WideUnsigned< W > &rhs) const
Comparison operators.
bool operator<(const WideUnsigned< W > &rhs) const
Comparison operators.
constexpr WideUnsigned(u32 hi, u32 lo)
Constructors for various input formats.
bool operator>=(const WideUnsigned< W > &rhs) const
Comparison operators.
constexpr WideUnsigned()
Constructors for various input formats.
bool operator<=(const WideUnsigned< W > &rhs) const
Comparison operators.
WideUnsigned< W > & operator=(const WideInteger< W > &rhs)
Constructors for various input formats.
Basic type aliases and prototypes used throughout SatCat5.
constexpr satcat5::util::uint128_t UINT128_ONE(u32(1))
Shorthand for commonly used constants.
constexpr satcat5::util::int256_t INT256_ZERO(u32(0))
Shorthand for commonly used constants.
constexpr satcat5::util::uint256_t UINT256_ONE(u32(1))
Shorthand for commonly used constants.
constexpr satcat5::util::int128_t INT128_ZERO(u32(0))
Shorthand for commonly used constants.
constexpr satcat5::util::int128_t INT128_ONE(u32(1))
Shorthand for commonly used constants.
constexpr satcat5::util::uint256_t UINT256_ZERO(u32(0))
Shorthand for commonly used constants.
constexpr satcat5::util::int256_t INT256_ONE(u32(1))
Shorthand for commonly used constants.
constexpr satcat5::util::uint512_t UINT512_ZERO(u32(0))
Shorthand for commonly used constants.
constexpr satcat5::util::uint128_t UINT128_ZERO(u32(0))
Shorthand for commonly used constants.
constexpr satcat5::util::int512_t INT512_ZERO(u32(0))
Shorthand for commonly used constants.
constexpr satcat5::util::int512_t INT512_ONE(u32(1))
Shorthand for commonly used constants.
constexpr satcat5::util::uint512_t UINT512_ONE(u32(1))
Shorthand for commonly used constants.