Skip to content

positional: Multi-Radix Positional Integer

integer is binary and edecimal is decimal. Both are the same idea at a different radix, and hard-coding the radix into each type means the arithmetic gets written twice.

positional parameterises it: a sign-magnitude integer in any radix, with one implementation of the carry-propagating algorithms serving all of them. That makes it the natural type for teaching how positional arithmetic works – showing the same addition in base 2, base 10 and base 16 – and for checking radix-specific code against an independent implementation.

#include <universal/number/positional/positional.hpp>
using namespace sw::universal;
positional<10, 10> a; // 10 digits, radix 10
positional<16, 2> b; // 16 digits, radix 2
template<unsigned ndigits, unsigned radix>
class positional;

ndigits is the number of digit positions; radix is the base each digit counts in. The value is sign-magnitude, so there is no two’s-complement wrap and no most-negative-value asymmetry – the sign is carried separately from the digits.

Property Value
Representation sign + ndigits digits in radix
Width fixed at compile time
Radix any, set by template parameter

ipow(a, n) is the exact integer power, with an unsigned or positional exponent and the same edge cases as integer’s.

It is built on blockdigit, the internal digit-vector engine that also backs the decimal types, so a bug fixed in one is fixed in all of them.

Like the other fixed-size integer types, positional takes its switches before the header:

  • literals in logic and arithmetic operators – enabled by default
  • throwing arithmetic exceptions – disabled by default; the default behaviour is a diagnostic on stderr for divide and modulo by zero

Both default inside the core header rather than the umbrella, so a translation unit that includes core.hpp directly gets the same behaviour.