Data representation 4: Performance, computer arithmetic

Overview

We look more deeply into the performance mystery of intsort, then explore some properties of computer integer arithmetic, including undefined behavior.

The intsort conundrum

An investigation

Analysis

Insertion order

Data structure Insertion order Elapsed times
std::list -r (random) 27.48 sec 27.45 sec 27.42 sec
std::vector -r 0.73 sec 0.73 sec 0.75 sec
std::list -u (increasing) 7.43 sec 7.43 sec 7.36 sec
std::vector -u 1.16 sec 1.14 sec 1.15 sec
std::list -d (decreasing) 0.01 sec 0.01 sec 0.01 sec
std::vector -d 0.35 sec 0.33 sec 0.34 sec

Integer questions

Benchmarking operations

int main(int argc, char* argv[]) {
    assert(argc == 2);
    unsigned long b = std::stoul(argv[1]);
    unsigned long n = 1'000'000'000;

    volatile unsigned long sum = 0;  // `volatile` inhibits optimizations
    for (unsigned long a = 0; a != n; ++a) {
      sum += a + b;
    }

    printf("%lu\n", sum);
}

Benchmark results

Bitwise arithmetic

Truth tables

~ output
0 1
1 0
& 0 1
0 0 0
1 0 1
| 0 1
0 0 1
1 1 1
^ 0 1
0 0 1
1 1 0

Beware precedence

From conventional to bitwise

Fun with bits

Integer overflow

Unsigned integer overflow

Negative unsigned numbers

Negation and bitwise

Two’s-complement representation

Signed integer overflow

More examples of undefined behaviors

Using bits

Bitset example