SatCat5
wide_integer.h
Go to the documentation of this file.
1 // Copyright 2022-2025 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
17 
18 #pragma once
19 
20 #include <satcat5/io_core.h>
21 #include <satcat5/log.h>
22 #include <satcat5/types.h>
23 
24 namespace satcat5 {
25  namespace util {
30  template <unsigned W> struct WideInteger {
31  public:
33  u32 m_data[W];
34 
38  template <unsigned W2>
40  { copy_from<W2>(rhs, rhs.sign_extend()); }
41 
42  template <unsigned W2>
44  { copy_from<W2>(rhs, 0); }
46 
48  inline unsigned width_bits() const { return 32 * W; }
50  inline unsigned width_words() const { return W; }
51 
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;
58  }
59  }
60  return 0;
61  }
62 
64  inline constexpr u32 sign_extend() const
65  { return sign_extend(s32(m_data[W-1])); }
66 
69  WideInteger<W>& operator++() { // ++myint
70  if (W > 0) ++m_data[0];
71  for (unsigned a = 0 ; a+1 < W ; ++a) {
72  if (m_data[a] != 0) break;
73  else ++m_data[a+1];
74  }
75  return *this;
76  }
77  WideInteger<W>& operator--() { // --myint
78  if (W > 0) --m_data[0];
79  for (unsigned a = 0 ; a+1 < W ; ++a) {
80  if (m_data[a] != UINT32_MAX) break;
81  else --m_data[a+1];
82  }
83  return *this;
84  }
85  WideInteger<W> operator++(int) { // myint++
86  WideInteger<W> tmp(*this); operator++(); return tmp;
87  }
88  WideInteger<W> operator--(int) { // myint--
89  WideInteger<W> tmp(*this); operator--(); return tmp;
90  }
92 
96  bool operator==(const WideInteger<W>& rhs) const {
97  unsigned match = 0;
98  for (unsigned a = 0 ; a < W ; ++a) {
99  if (m_data[a] == rhs.m_data[a]) ++match;
100  }
101  return (match == W);
102  }
103 
104  inline bool operator!=(const WideInteger<W>& rhs) const {
105  return !operator==(rhs);
106  }
108 
111  explicit operator bool() const {
112  u32 any = 0;
113  for (unsigned a = 0 ; a < W ; ++a) {
114  any |= m_data[a];
115  }
116  return (any > 0);
117  }
118  explicit constexpr operator int32_t() const {
119  return (int32_t)uint32_t(*this);
120  }
121  explicit constexpr operator int64_t() const {
122  return (int64_t)uint64_t(*this);
123  }
124  explicit constexpr operator uint32_t() const {
125  return (W > 0) ? m_data[0] : 0;
126  }
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);
130  }
132 
134  void log_to(satcat5::log::LogBuffer& obj) const {
135  obj.wr_str(" = 0x");
136  for (unsigned a = W-1 ; a < UINT_MAX ; --a) {
137  obj.wr_h32(m_data[a]);
138  if (a) obj.wr_str("-");
139  }
140  }
141 
144  if (rd->get_read_ready() >= 4*W) {
145  for (unsigned a = W-1 ; a < UINT_MAX ; --a) {
146  m_data[a] = rd->read_u32();
147  }
148  return true;
149  } else {
150  return false;
151  }
152  }
153 
156  for (unsigned a = W-1 ; a < UINT_MAX ; --a) {
157  wr->write_u32(m_data[a]);
158  }
159  }
160 
161  protected:
164 
168  WideInteger() = default;
169  constexpr explicit WideInteger(u32 rhs)
170  : m_data{u32(rhs)} {}
171  constexpr explicit WideInteger(u64 rhs)
172  : m_data{u32(rhs >> 0), u32(rhs >> 32)} {}
173  constexpr WideInteger(u32 hi, u32 lo)
174  : m_data{lo, hi} {}
175 
176  explicit WideInteger(s32 rhs)
177  : m_data{u32(rhs)}
178  {
179  for (unsigned a = 1 ; a < W ; ++a)
180  m_data[a] = sign_extend(rhs);
181  }
182 
183  explicit WideInteger(s64 rhs)
184  : m_data{u32(rhs >> 0), u32(rhs >> 32)}
185  {
186  for (unsigned a = 2 ; a < W ; ++a)
187  m_data[a] = sign_extend(rhs);
188  }
189 
190  // Internal helper functions.
191  template <typename T> static inline constexpr u32 sign_extend(T x)
192  { return u32((x < 0) ? -1 : 0); }
193 
194  template <unsigned W2>
195  void copy_from(const satcat5::util::WideInteger<W2>& rhs, u32 ext) {
196  for (unsigned a = 0 ; a < W ; ++a) {
197  m_data[a] = (a < W2) ? rhs.m_data[a] : ext;
198  }
199  }
200 
201  // Internal arithmetic functions.
202  // Note: These cannot be inherited directly because we need the
203  // signed/unsigned type to be retained, so we use indirection.
204  WideInteger<W> add(const WideInteger<W>& rhs) const {
205  // Modulo-add all the individual terms.
206  WideInteger<W> tmp;
207  for (unsigned a = 0 ; a < W ; ++a) {
208  tmp.m_data[a] = m_data[a] + rhs.m_data[a];
209  }
210  // Wraparound on any term gives +1 carry to the next term.
211  // Special case if that's just enough to double-rollover.
212  bool carry = false;
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;
218  } else {
219  carry = false;
220  }
221  }
222  return tmp;
223  }
224 
225  void add_in_place(const WideInteger<W>& rhs) {
226  // Modulo-add all the individual terms.
227  for (unsigned a = 0 ; a < W ; ++a) {
228  m_data[a] += rhs.m_data[a];
229  }
230  // Wraparound on any term gives +1 carry to the next term.
231  // Special case if that's just enough to double-rollover.
232  bool carry = false;
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;
238  } else {
239  carry = false;
240  }
241  }
242  }
243 
244  WideInteger<W> subtract(const WideInteger<W>& rhs) const {
245  // Modulo-subtract all the individual terms.
246  WideInteger<W> tmp;
247  for (unsigned a = 0 ; a < W ; ++a) {
248  tmp.m_data[a] = m_data[a] - rhs.m_data[a];
249  }
250  // Wraparound on any term gives -1 carry from the next term.
251  // Special case if that's just enough to double-rollover.
252  bool carry = false;
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;
258  } else {
259  carry = false;
260  }
261  }
262  return tmp;
263  }
264 
265  WideInteger<W> multiply(const WideInteger<W>& rhs) const {
266  // Calculate, scale, and sum each of the inner-product terms.
267  // (Skip any that fall outside the useful dynamic range.)
268  WideInteger<W> sum(u32(0));
269  for (unsigned a = 0 ; a < W ; ++a) {
270  for (unsigned b = 0 ; a + b < W ; ++b) {
271  u64 aa = (u64)m_data[a];
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));
276  }
277  }
278  return sum;
279  }
280 
281  WideInteger<W> shift_left(unsigned rhs) const {
282  unsigned rw = rhs / 32; // Words to shift
283  unsigned rb = rhs % 32; // Bits to shift
284  unsigned rc = 32 - rb; // Complement of rb
285  WideInteger<W> tmp;
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;
290  }
291  return tmp;
292  }
293 
294  WideInteger<W> shift_right(unsigned rhs, u32 ext) const {
295  unsigned rw = rhs / 32; // Words to shift
296  unsigned rb = rhs % 32; // Bits to shift
297  unsigned rc = 32 - rb; // Complement of rb
298  WideInteger<W> tmp;
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;
303  }
304  return tmp;
305  }
306 
307  WideInteger<W> bitwise_invert() const {
308  WideInteger<W> tmp;
309  for (unsigned a = 0 ; a < W ; ++a) {
310  tmp.m_data[a] = ~m_data[a];
311  }
312  return tmp;
313  }
314 
315  void bitwise_or(const WideInteger<W>& rhs) {
316  for (unsigned a = 0 ; a < W ; ++a) {
317  m_data[a] |= rhs.m_data[a];
318  }
319  }
320 
321  void bitwise_and(const WideInteger<W>& rhs) {
322  for (unsigned a = 0 ; a < W ; ++a) {
323  m_data[a] &= rhs.m_data[a];
324  }
325  }
326 
327  void bitwise_xor(const WideInteger<W>& rhs) {
328  for (unsigned a = 0 ; a < W ; ++a) {
329  m_data[a] ^= rhs.m_data[a];
330  }
331  }
332  };
333 
335  template <unsigned W> struct WideSigned final
336  : public satcat5::util::WideInteger<W>
337  {
338  public:
341  constexpr WideSigned()
342  : satcat5::util::WideInteger<W>() {}
343  constexpr explicit WideSigned(u32 rhs)
344  : satcat5::util::WideInteger<W>(rhs) {}
345  constexpr explicit WideSigned(u64 rhs)
346  : satcat5::util::WideInteger<W>(rhs) {}
347  constexpr WideSigned(u32 hi, u32 lo)
348  : satcat5::util::WideInteger<W>(hi, lo) {}
349  explicit WideSigned(s32 rhs)
350  : satcat5::util::WideInteger<W>(rhs) {}
351  explicit WideSigned(s64 rhs)
352  : satcat5::util::WideInteger<W>(rhs) {}
354  { this->copy_from(rhs, 0); }
356  { this->copy_from(rhs, 0); return *this; }
358 
360  bool is_negative() const {
361  return this->m_data[W-1] >= 0x80000000u;
362  }
363 
366  return is_negative() ? -(*this) : (*this);
367  }
368 
370  void clamp(const WideSigned<W>& limit_pos) {
371  const WideSigned<W> limit_neg(-limit_pos);
372  if (*this > limit_pos) *this = limit_pos;
373  if (*this < limit_neg) *this = limit_neg;
374  }
375 
380  { WideSigned<W> tmp(~(*this)); ++tmp; return tmp; }
381  inline WideSigned<W> operator+(const WideInteger<W>& rhs) const
382  { return this->add(rhs); }
384  { this->add_in_place(rhs); return *this; }
385  inline WideSigned<W> operator-(const WideInteger<W>& rhs) const
386  { return this->subtract(rhs); }
388  { *this = this->subtract(rhs); return *this; }
389  inline WideSigned<W> operator*(const WideInteger<W>& rhs) const
390  { return this->multiply(rhs); }
392  { *this = this->multiply(rhs); return *this; }
393  inline WideSigned<W> operator/(const WideSigned<W>& rhs) const
394  { WideSigned<W> d, m; this->divmod(rhs, d, m); return d; }
395  inline WideSigned<W> operator%(const WideSigned<W>& rhs) const
396  { WideSigned<W> d, m; this->divmod(rhs, d, m); return m; }
398  { *this = *this / rhs; return *this; }
400  { *this = *this % rhs; return *this; }
401  inline WideSigned<W> operator<<(unsigned rhs) const
402  { return this->shift_left(rhs); }
403  inline WideSigned<W> operator<<=(unsigned rhs)
404  { *this = this->shift_left(rhs); return *this; }
405  inline WideSigned<W> operator>>(unsigned rhs) const
406  { return this->shift_right(rhs, this->sign_extend()); }
407  inline WideSigned<W> operator>>=(unsigned rhs)
408  { *this = *this >> rhs; return *this; }
409  inline WideSigned<W> operator~() const
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; }
417  inline WideSigned<W> operator|(const WideInteger<W>& rhs) const
418  { WideInteger<W> tmp(*this); tmp.bitwise_or(rhs); return tmp; }
419  inline WideSigned<W> operator&(const WideInteger<W>& rhs) const
420  { WideInteger<W> tmp(*this); tmp.bitwise_and(rhs); return tmp; }
421  inline WideSigned<W> operator^(const WideInteger<W>& rhs) const
422  { WideInteger<W> tmp(*this); tmp.bitwise_xor(rhs); return tmp; }
424 
426  void divmod(const WideSigned<W>& rhs,
427  WideSigned<W>& div, WideSigned<W>& mod) const
428  {
429  // Unsigned division on the absolute value of each input.
430  satcat5::util::WideUnsigned<W> unum(this->abs());
433  unum.divmod(urhs, udiv, umod);
434  // Convert sign of outputs using the "x = d*y + m" identity.
435  div = (is_negative() == rhs.is_negative()) ? udiv : -udiv;
436  mod = is_negative() ? -umod : umod;
437  }
438 
441  // Unsigned division on the absolute value of each input.
442  satcat5::util::WideUnsigned<W> unum(this->abs());
444  satcat5::util::WideUnsigned<W> udiv = unum.div_round(urhs);
445  // Convert sign of outputs using the "x = d*y + m" identity.
446  return (is_negative() == rhs.is_negative()) ? udiv : -udiv;
447  }
448 
451  bool operator<(const WideSigned<W>& rhs) const {
452  if (W == 0) return false;
453  // Compare the most significant word as a signed integer.
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;
456  // Remaining words are compared as unsigned integers.
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;
460  }
461  return false; // All fields equal.
462  }
463  bool operator>(const WideSigned<W>& rhs) const {
464  if (W == 0) return false;
465  // Compare the most significant word as a signed integer.
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;
468  // Remaining words are compared as unsigned integers.
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;
472  }
473  return false; // All fields equal.
474  }
475  inline bool operator<=(const WideSigned<W>& rhs) const {
476  return !operator>(rhs);
477  }
478  inline bool operator>=(const WideSigned<W>& rhs) const {
479  return !operator<(rhs);
480  }
482  };
483 
485  template <unsigned W> struct WideUnsigned final
486  : public satcat5::util::WideInteger<W>
487  {
488  public:
491  constexpr WideUnsigned()
492  : satcat5::util::WideInteger<W>() {}
493  constexpr explicit WideUnsigned<W>(u32 rhs)
494  : satcat5::util::WideInteger<W>(rhs) {}
495  constexpr explicit WideUnsigned<W>(u64 rhs)
496  : satcat5::util::WideInteger<W>(rhs) {}
497  constexpr WideUnsigned(u32 hi, u32 lo)
498  : satcat5::util::WideInteger<W>(hi, lo) {}
500  { this->copy_from(rhs, 0); }
502  { this->copy_from(rhs, 0); return *this; }
504 
508  { WideUnsigned<W> tmp(~(*this)); ++tmp; return tmp; }
509  inline WideUnsigned<W> operator+(const WideInteger<W>& rhs) const
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; }
553 
555  void divmod(const WideUnsigned<W>& rhs,
556  WideUnsigned<W>& div, WideUnsigned<W>& mod) const
557  {
558  // Shortcuts for unusual edge-cases.
559  static constexpr WideUnsigned<W> ZERO(u32(0));
560  static constexpr WideUnsigned<W> ONE(u32(1));
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;}
564  // Order-of-magnitude estimate of the result.
565  unsigned msb = 1 + this->msb() - rhs.msb();
566  // Use the serial bit-at-a-time method.
567  mod = *this; div = ZERO;
568  for (unsigned b = msb ; b < UINT_MAX ; --b) {
569  WideUnsigned<W> tmp(rhs << b);
570  if (mod >= tmp) {
571  div.m_data[b/32] |= (1u << (b%32));
572  mod -= tmp;
573  }
574  }
575  }
576 
579  bool operator<(const WideUnsigned<W>& rhs) const {
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;
583  }
584  return false; // All fields equal.
585  }
586  bool operator>(const WideUnsigned<W>& rhs) const {
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;
590  }
591  return false; // All fields equal.
592  }
593  inline bool operator<=(const WideUnsigned<W>& rhs) const {
594  return !operator>(rhs);
595  }
596  inline bool operator>=(const WideUnsigned<W>& rhs) const {
597  return !operator<(rhs);
598  }
600  };
601 
611 
627  }
628 }
Abstract API for reading byte-streams and packets.
Definition: io_readable.h:68
virtual unsigned get_read_ready() const =0
How many bytes can be read without blocking?
Abstract API for writing byte-streams and packets.
Definition: io_writeable.h:24
Internal buffer used by the Log class.
Definition: log.h:134
void wr_h32(u32 val, unsigned nhex=8)
Write an integer (u32) in hexadecimal format.
Definition: log.cc:303
void wr_str(const char *str)
Write a null-terminated UTF-8 string.
Definition: log.cc:297
I/O interface core definitions.
Diagnostic logging to UART and/or Ethernet ports.
Wide-integer parent class.
Definition: wide_integer.h:30
bool operator==(const WideInteger< W > &rhs) const
Equality comparison only.
Definition: wide_integer.h:96
bool read_from(satcat5::io::Readable *rd)
Read binary data from a given source.
Definition: wide_integer.h:143
unsigned width_bits() const
Total width in bits.
Definition: wide_integer.h:48
WideInteger< W > operator--(int)
Increment/decrement.
Definition: wide_integer.h:88
bool operator!=(const WideInteger< W > &rhs) const
Equality comparison only.
Definition: wide_integer.h:104
WideInteger< W > operator++(int)
Increment/decrement.
Definition: wide_integer.h:85
WideInteger< W > & operator++()
Increment/decrement.
Definition: wide_integer.h:69
void write_to(satcat5::io::Writeable *wr) const
Write binary data from a given sink.
Definition: wide_integer.h:155
WideInteger()=default
Constructors are private to force use of child classes.
u32 m_data[W]
Underlying data vector, LSW-first.
Definition: wide_integer.h:33
unsigned width_words() const
Total width in 32-bit words.
Definition: wide_integer.h:50
void log_to(satcat5::log::LogBuffer &obj) const
Human-readable logging in hexadecimal format.
Definition: wide_integer.h:134
WideInteger(const satcat5::util::WideSigned< W2 > &rhs)
Implicit size-converting copy constructors must know if the input is signed or unsigned to proceed.
Definition: wide_integer.h:39
WideInteger(const satcat5::util::WideUnsigned< W2 > &rhs)
Implicit size-converting copy constructors must know if the input is signed or unsigned to proceed.
Definition: wide_integer.h:43
unsigned msb() const
Index of most significant '1' bit.
Definition: wide_integer.h:53
WideInteger< W > & operator--()
Increment/decrement.
Definition: wide_integer.h:77
constexpr u32 sign_extend() const
Extend most significant word with either "0" or "FFFF...".
Definition: wide_integer.h:64
Template for signed integers.
Definition: wide_integer.h:337
WideSigned< W > operator+(const WideInteger< W > &rhs) const
Common arithmetic operators.
Definition: wide_integer.h:381
WideSigned< W > operator~() const
Common arithmetic operators.
Definition: wide_integer.h:409
WideSigned(const satcat5::util::WideInteger< W > &rhs)
Constructors for various input formats.
Definition: wide_integer.h:353
WideSigned(s64 rhs)
Constructors for various input formats.
Definition: wide_integer.h:351
WideSigned< W > operator/(const WideSigned< W > &rhs) const
Common arithmetic operators.
Definition: wide_integer.h:393
WideSigned< W > & operator^=(const WideInteger< W > &rhs)
Common arithmetic operators.
Definition: wide_integer.h:415
WideSigned< W > & operator|=(const WideInteger< W > &rhs)
Common arithmetic operators.
Definition: wide_integer.h:411
WideSigned< W > operator-(const WideInteger< W > &rhs) const
Common arithmetic operators.
Definition: wide_integer.h:385
bool is_negative() const
Is this integer negative, i.e., x < 0?
Definition: wide_integer.h:360
WideSigned< W > operator%(const WideSigned< W > &rhs) const
Common arithmetic operators.
Definition: wide_integer.h:395
bool operator<(const WideSigned< W > &rhs) const
Comparison operators.
Definition: wide_integer.h:451
constexpr WideSigned(u32 hi, u32 lo)
Constructors for various input formats.
Definition: wide_integer.h:347
WideSigned< W > operator&(const WideInteger< W > &rhs) const
Common arithmetic operators.
Definition: wide_integer.h:419
void divmod(const WideSigned< W > &rhs, WideSigned< W > &div, WideSigned< W > &mod) const
Combined divide + modulo function.
Definition: wide_integer.h:426
bool operator>(const WideSigned< W > &rhs) const
Comparison operators.
Definition: wide_integer.h:463
void clamp(const WideSigned< W > &limit_pos)
Clamp input to +/- limit_pos.
Definition: wide_integer.h:370
constexpr WideSigned(u32 rhs)
Constructors for various input formats.
Definition: wide_integer.h:343
satcat5::util::WideSigned< W > abs() const
Absolute value.
Definition: wide_integer.h:365
WideSigned< W > div_round(const WideSigned< W > &rhs) const
Divide and round toward zero.
Definition: wide_integer.h:440
WideSigned< W > operator*(const WideInteger< W > &rhs) const
Common arithmetic operators.
Definition: wide_integer.h:389
WideSigned< W > operator>>=(unsigned rhs)
Common arithmetic operators.
Definition: wide_integer.h:407
WideSigned< W > & operator%=(const WideInteger< W > &rhs)
Common arithmetic operators.
Definition: wide_integer.h:399
WideSigned< W > operator>>(unsigned rhs) const
Common arithmetic operators.
Definition: wide_integer.h:405
WideSigned< W > & operator*=(const WideInteger< W > &rhs)
Common arithmetic operators.
Definition: wide_integer.h:391
WideSigned< W > operator<<(unsigned rhs) const
Common arithmetic operators.
Definition: wide_integer.h:401
constexpr WideSigned()
Constructors for various input formats.
Definition: wide_integer.h:341
WideSigned< W > operator^(const WideInteger< W > &rhs) const
Common arithmetic operators.
Definition: wide_integer.h:421
constexpr WideSigned(u64 rhs)
Constructors for various input formats.
Definition: wide_integer.h:345
WideSigned< W > & operator=(const WideInteger< W > &rhs)
Constructors for various input formats.
Definition: wide_integer.h:355
WideSigned< W > operator<<=(unsigned rhs)
Common arithmetic operators.
Definition: wide_integer.h:403
WideSigned< W > & operator-=(const WideInteger< W > &rhs)
Common arithmetic operators.
Definition: wide_integer.h:387
bool operator>=(const WideSigned< W > &rhs) const
Comparison operators.
Definition: wide_integer.h:478
WideSigned< W > & operator&=(const WideInteger< W > &rhs)
Common arithmetic operators.
Definition: wide_integer.h:413
bool operator<=(const WideSigned< W > &rhs) const
Comparison operators.
Definition: wide_integer.h:475
WideSigned< W > & operator+=(const WideInteger< W > &rhs)
Common arithmetic operators.
Definition: wide_integer.h:383
WideSigned< W > operator|(const WideInteger< W > &rhs) const
Common arithmetic operators.
Definition: wide_integer.h:417
WideSigned< W > & operator/=(const WideInteger< W > &rhs)
Common arithmetic operators.
Definition: wide_integer.h:397
WideSigned< W > operator-() const
Common arithmetic operators.
Definition: wide_integer.h:379
WideSigned(s32 rhs)
Constructors for various input formats.
Definition: wide_integer.h:349
Template for unsigned integers.
Definition: wide_integer.h:487
void divmod(const WideUnsigned< W > &rhs, WideUnsigned< W > &div, WideUnsigned< W > &mod) const
Combined divide + modulo function.
Definition: wide_integer.h:555
WideUnsigned(const satcat5::util::WideInteger< W > &rhs)
Constructors for various input formats.
Definition: wide_integer.h:499
WideUnsigned< W > operator-() const
Common arithmetic operators.
Definition: wide_integer.h:507
bool operator>(const WideUnsigned< W > &rhs) const
Comparison operators.
Definition: wide_integer.h:586
bool operator<(const WideUnsigned< W > &rhs) const
Comparison operators.
Definition: wide_integer.h:579
constexpr WideUnsigned(u32 hi, u32 lo)
Constructors for various input formats.
Definition: wide_integer.h:497
bool operator>=(const WideUnsigned< W > &rhs) const
Comparison operators.
Definition: wide_integer.h:596
constexpr WideUnsigned()
Constructors for various input formats.
Definition: wide_integer.h:491
bool operator<=(const WideUnsigned< W > &rhs) const
Comparison operators.
Definition: wide_integer.h:593
WideUnsigned< W > & operator=(const WideInteger< W > &rhs)
Constructors for various input formats.
Definition: wide_integer.h:501
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.