Alignment padding bound 2026-11-05
The alignment padding bound limits the extra bytes needed to move an integer payload address to the next permitted memory alignment. Let be the first address after an allocated header, and let alignment require a multiple of a positive integer . Withthe exact bound is . It applies to the earliest aligned start, not to arbitrary extra space an allocator may choose to reserve.
To prove the bound, write . The ceiling function gives , hence . Since is an integer number of bytes, . The endpoints can occur: an already aligned gives zero padding, while one byte beyond an aligned address gives . This is also the statement that is the least nonnegative residue of in modular arithmetic.
For an original example, , header size and block start give , and . The worst-case bound is attained. Starting at instead gives and . Identical header and payload sizes can therefore incur different allocation alignment padding at different addresses.
A sufficient address-independent reservation for a payload of bytes is , before any trailer, block rounding or minimum free-block size constraint. For , and ,47 bytes suffice under precisely that layout. A known starting address can require less: needs5 bytes of padding and a37-byte used prefix. Separating the payload from its metadata is the bookkeeping principle illustrated in OSTEP; the bound adds a worst-case alignment allowance.[ref]
Operating Systems: Three Easy Pieces by Remzi H. Arpaci-Dusseau and others. Chapter17, §17.2, allocation header versus payload, printed pp.5–6
These inequalities concern mathematical integers. An implementation using bounded address arithmetic must separately prevent integer overflow when adding the header, padding allowance or payload. A wrapped sum cannot be justified by a correct bound over unbounded integers.
C programming language 2026-10-24
A systems programming language supporting explicit memory access, arrays, and implementation-dependent integer widths. Signed integer overflow is not generally specified as modular arithmetic; correctness arguments must state the relevant range assumptions.
Digit-array integer representation 2026-10-31
Store an integer in a nonempty array of numeral digits, with the least significant digit first and a fixed radix . Normalized digits satisfy . High-order zeros do not change the value. Adding digit arrays coefficientwise or multiplying them by discrete convolution gives the correct value before normalization, because these operations add or multiply the corresponding powers of the radix. Exact temporary arithmetic, or a radix and accumulator size chosen to prevent integer overflow, is required.
For each candidate first index in a sorted array, use lower-bound search for only in the suffix starting at . A matching result is automatically at a different position. The outer loop invariant excludes all solutions whose smaller index precedes ; an unsuccessful suffix search extends this exclusion by one. Exhaustion proves absence of any pair. Searching all suffixes gives running time and constant auxiliary space. Compute the complement in a sufficiently wide type to avoid integer overflow before comparison.
Exponential sign bracketing Created 2026-10-24 Updated 2026-11-05
Exponential sign bracketing finds an integer interval with opposite endpoint signs before sign-bracketing binary search. Suppose is defined on nonnegative integers, its signs can be evaluated exactly, , and for all sufficiently large integers . Test . An exact zero can be returned immediately; otherwise stop at the first positive endpoint and retain the preceding negative endpoint, or zero when .
Excluding the already known evaluation at zero, this takes endpoint tests. For , the final integer interval is , of width . Repeated midpoint tests preserving opposite endpoint signs take further tests to reach adjacent integers, unless an exact zero is found earlier. For , is already adjacent.
No monotonicity is needed to preserve opposite endpoint signs, though other crossings may be skipped. Adjacent opposite signs do not imply an integer root; for , neither endpoint of is a root. A real-valued extension requires continuity to infer a real root by the intermediate value theorem. A machine implementation must handle integer overflow and unreliable floating-point arithmetic; mathematical termination does not ensure representable endpoints.
Fixed-point arithmetic Created 2026-10-20 Updated 2026-11-05
Fixed-point arithmetic represents values as integer multiples of a fixed scale . Integer operations on , followed by the required rescaling and rounding, implement arithmetic on these values. Unlike floating-point arithmetic, the spacing is constant throughout the representable range.
For , the stored integer represents . Multiplying two encoded values and gives , so returning to the original scale requires dividing the integer product by with a stated rounding rule. Fixed spacing makes resolution predictable, but the chosen integer width limits range and can cause integer overflow.
Formal verification Created 2026-10-13 Updated 2026-10-18
Establishing specified properties of a system using formal proofs about a precise model. Formal verification connects an implementation to a formal specification; correctness of the model and its assumptions still matters when applying the result to a physical system.
For a small example, the summation loop verification below starts with executable steps and asks two separate questions: does any returned value satisfy the postcondition, and does execution reach that return? A loop invariant answers the first; a loop variant answers the second. This turns an unbounded family of permitted inputs into a few reusable proof obligations.
The model must specify programming language semantics, including the meaning of variable assignments, comparisons and integer arithmetic. A proof about exact mathematical integers need not describe a machine that wraps on integer overflow. Similarly, a correct formal proof of a weak or mistaken formal specification does not establish the intended behavior. Choosing the right formal specification and relating the model to the implemented system remain substantive tasks.
Software testing examines chosen executions and can expose a counterexample. A formal proof instead justifies a statement throughout its stated model; it does not require executing every permitted input. This makes formal verification valuable when rare boundary cases matter, while software testing can still reveal an incorrect model or misunderstood requirement.
In 1969, Tony Hoare presented rules for variable assignment, composition and iteration in a small programming language. His paper explicitly says those rules do not prove successful termination, and discusses the dependence of arithmetic reasoning on the chosen overflow behavior. These reservations already make the model's scope part of the argument.[ref]
An Axiomatic Basis for Computer Programming by Tony Hoare. Hoare, An Axiomatic Basis for Computer Programming, §2 Computer Arithmetic, pp. 576–577; §§3.1–3.4, pp. 577–578; §4 General Reservations, pp. 578–579
Hoare logic Created 2026-10-18 Updated 2026-11-05
Hoare logic proves properties of programs through Hoare triples . A precondition constrains initial states and a postcondition constrains returned states. The basic rules establish partial correctness; termination requires a further argument.[ref]
For a program expression whose evaluation is defined and has no side effects, the assignment rule isThe substitution replaces the free occurrences of in the desired postcondition. For example, obtaining after
x := x+1 requires beforehand, so suffices. Integer overflow must be excluded or handled by the stated arithmetic model.Sequential composition joins a first postcondition to the next precondition. For a while loop, proving establishesHere is the loop invariant. For
while x > 0 do x := x-1, starting with an exact nonnegative integer, is preserved and the false exit guard yields . The decreasing nonnegative integer is also a loop variant, establishing total correctness for this example.[ref] Integer logarithm 2026-10-31
For integers and , the integer logarithm is the largest nonnegative integer such that . Equivalently,The equivalence follows from the monotonicity of exponentiation in its exponent and the definition of the floor function. For example, , so the base-three integer logarithm of is .
A multiplication loop maintains and accepts another factor while . Repeated squaring makes the search faster: precompute starting at , and consider these factors in decreasing . Include a factor when the accumulated product remains at most . If , the loop invariant before considering is . Accepting exactly when halves that uncertainty, proving the greedy algorithm returns . This takes arithmetic operations; it is not the same claim as this bound on bit complexity.
For positive operands in bounded integer arithmetic, test before multiplying by . Integer division makes this equivalent to while preventing integer overflow in a rejected candidate.
Length-prefix validation before allocation 2026-11-05
Length-prefix validation before allocation checks that an encoded payload length is permitted and safely usable before requesting memory allocation based on it. A fixed-width length field bounds what the encoding can represent; an application can impose a smaller limit. TLS vectors, for example, have explicitly specified minimum and maximum byte lengths.[ref]
The Transport Layer Security Protocol Version 1.3 (RFC 8446). §3.4, variable-length vectors and permitted bounds
For an original decoder model, let be the decoded unsigned payload length, the application limit and the bytes remaining in a complete input buffer after the prefix. Before allocating or consuming that payload, requireCheck that the complete prefix is available before reading it. For a two-byte big-endian prefix
02 01, . With and , the input fails both checks. Prefix 01 2c instead declares bytes and satisfies these two bounds. The example counts only payload bytes in .Arithmetic needs its own bound. If an allocation includes additional bytes and the size type's maximum value is , verify and before forming . Computing the sum first can already cause integer overflow. Similarly, when allocating elements of positive size , check before multiplication.
For a streaming decoder, can mean that more input is needed rather than that the final message is malformed. It still does not justify consuming unavailable bytes or allocating beyond the stated resource limit. Nested fields need bounds relative to their enclosing field. These checks establish safe structural handling of a length-prefixed encoding; they do not authenticate the sender or validate the payload's meaning.
Three advantages of integer arithmetic for raster graphics are:
- Cheap, fast operations. Historically, integer addition, subtraction and shifts needed much less hardware and execution time than floating-point arithmetic, especially on machines without a floating-point unit. An incremental Bresenham's line algorithm needs only a few additions and a decision per pixel.
- Exact decisions. Provided integer overflow is excluded, the scaled midpoint line decision is exact. There is no accumulated rounding error that can move a decision across a half-pixel boundary; equality has a reproducible tie rule.
- Simple storage and hardware. Integer coordinates already identify pixels. An implementation can keep coordinates and decision variables in ordinary registers and use a small add/compare datapath, avoiding conversion between floating-point numbers and integer screen addresses.
Multiply the midpoint line decision by two to remove the fraction. At the current pixel , maintainAt the initial endpoint this is . If is chosen, the next decision midpoint is displaced by and increases by . If is chosen, its displacement is and increases by . Both increments are constant, so the per-pixel work uses only integer arithmetic:The completed code, using the tie rule of part (b), is:
void midpointLine(int x0, int y0, int x1, int y1)
{
int dx, dy, incrE, incrNE, d, x, y;
x = x0; y = y0;
dx = x1 - x0;
dy = y1 - y0;
incrE = 2 * dy;
incrNE = 2 * (dy - dx);
d = 2 * dy - dx;
drawPoint(x, y);
while (x < x1) {
if (d < 0) {
d += incrE;
} else {
d += incrNE;
y++;
}
x++;
drawPoint(x, y);
}
return;
}Thus
guard1 is x < x1, and guard2 is d < 0. Multiplication by two is the only multiplication. Signed decision variables are convenient because and incrNE can be negative; this remains an integer arithmetic algorithm. A strictly unsigned hardware representation would need an equivalent biased or separated-sign encoding. As with the printed int skeleton, assume all intermediate values fit the chosen type; integer overflow would invalidate the mathematical decisions.To verify the geometry, write . The chosen ordinate isThe midpoint line decision selects exactly this nearest integer, rounding halves upward. Its increment between successive columns is zero or one. At and , it gives exactly and , respectively, so both endpoints are included and the line segment has precisely distinct pixels.
For the illustrated endpoints and , the ordinates are . In particular the exact ordinate at is , and the chosen pixel is .
Represent a wall by a list of rows indexed by height. Within each row keep brick placements sorted by their left coordinate, with disjoint occupied half-open intervals. The public
Brick in the paper is a mutable input specification; internal placements snapshot its width and colour, so later client edits cannot invalidate an existing wall. Empty intermediate rows cannot occur in a supportive wall with occupied rows above them.The following Java uses
import java.util.*; and import java.awt.Color;. Keep the source's Brick input software class. All other representation types are private nested software classes of Wall, which prevents clients from inserting directly into a row. The row(int y) query returns a detached row for the equality operation in part (e).final class Wall {
private static final class Placed {
final long x, end;
final Color colour;
Placed(long x, int width, Color colour) {
this.x = x;
this.end = x + width;
this.colour = colour;
}
}
private static final class Row {
private final List<Placed> bricks = new ArrayList<Placed>();
boolean contains(long x) {
for (Placed b : bricks) {
if (x < b.x) return false;
if (x < b.end) return true;
}
return false;
}
boolean canInsert(Placed b) {
for (Placed old : bricks)
if (b.x < old.end && old.x < b.end) return false;
return true;
}
void insert(Placed b) {
int i = 0;
while (i < bricks.size() && bricks.get(i).x < b.x) ++i;
bricks.add(i, b);
}
Row copy() {
Row r = new Row();
r.bricks.addAll(bricks);
return r;
}
// Insert the equality members from part (e) here.
}
private final List<Row> rows = new ArrayList<Row>();
public void addBrick(Brick b, int x, int y) throws Exception {
if (b == null || b.col == null || b.width <= 0 || y < 0)
throw new Exception("invalid brick or height");
// Snapshot mutable input. Long arithmetic protects x + width.
int width = b.width;
Color colour = new Color(b.col.getRGB(), true);
Placed placed = new Placed((long) x, width, colour);
if (y > rows.size()) throw new Exception("unsupported height");
Row target = y == rows.size() ? new Row() : rows.get(y);
if (!target.canInsert(placed)) throw new Exception("overlap");
if (y > 0) {
Row below = rows.get(y - 1);
if (!below.contains(placed.x) || !below.contains(placed.end - 1))
throw new Exception("unsupported end");
}
// All checks precede the first modification of this wall.
target.insert(placed);
if (y == rows.size()) rows.add(target);
}
public boolean contains(int x, int y) {
return y >= 0 && y < rows.size() && rows.get(y).contains((long) x);
}
public Object row(int y) {
if (y < 0) throw new IllegalArgumentException("negative row");
return y < rows.size() ? rows.get(y).copy() : new Row();
}
}Here
Placed instances and their captured Color values are immutable objects, so copying a row's outer list suffices to create a detached snapshot. Returning its static type as Object exposes just the equality operation needed below, without exposing a mutable row API. A fuller application could instead return an immutable row-view object interface.The empty list represents a valid supportive wall. A rejected insertion performs no wall update. On success, the overlap test establishes validity in the target row; all other rows are unchanged. The support checks establish support for the new brick; adding material cannot remove support from old bricks. Appending a row only at the current height count keeps the row representation contiguous. Integer overflow in a right endpoint is prevented by converting the horizontal coordinate to
long before adding the positive int width. For instance, a brick at Integer.MAX_VALUE can still have a mathematically meaningful right endpoint.An -bit two's complement word represents the integerThe leading bit has negative weight. Words beginning with zero encode the nonnegative values; words beginning with one encode the negative values. Equivalently, interpret the whole word as unsigned and subtract when its leading bit is one. For example, the four-bit words
0111, 1000, and 1111 encode , , and respectively. The range is asymmetric: the most negative value has no positive counterpart in the same number of bits.For a nonzero representable magnitude, complementing all bits and adding one obtains its negative modulo . Fixed-width addition can therefore use the same low-order binary numeral system addition circuitry for signed and unsigned operands; interpreting the result as signed requires detecting integer overflow.
Solutions to all eight questions of the 12 June 2013 paper. The Scala code uses the paper's Scala 2 conventions. Arithmetic is exact unless a machine type is explicitly discussed; in particular, Question 1 permits ignoring integer overflow. Each code block extends the implementation introduced in its question, unless it supplies a complete replacement.[ref]
Imperative Programming examination paper by the University of Oxford (2013). Cover and printed pp. 2–11, Questions 1–8
Keep a running total in the mixin, and use only the inherited public operations. Updating after a successful superclass operation leaves the total unchanged if an empty For this trait mixed directly into
pop fails its precondition.trait SumPlugin extends Stack {
private var total = 0
override def push(x: Int): Unit = {
super.push(x)
total += x
}
override def pop(): Int = {
val x = super.pop()
total -= x
x
}
def sum: Int = total
}Stack, its representation invariant is , where is the abstract stack sequence. A successful push adds exactly its argument and a successful pop removes exactly its returned value. ThusThe mixin reads no private Stack fields. Its operations add constant time complexity. As in the paper's Int interface, an unbounded mathematical total requires excluding integer overflow, or replacing the accumulator with BigInt if the interface is allowed to change. A later mixin can transform a pushed value at a different point in the Scala trait linearization; the effect is analyzed in the next part.Keep the neighboring Fibonacci number in a private closure. Before calling the transition with , let its captured The transition returns and stores , preserving the paired Fibonacci recurrence. Initialization gives and , soUsing
following equal .def fibonacci(): Iter[BigInt] = {
var following = BigInt(1)
val step: BigInt => BigInt = (x: BigInt) => {
val result = following
following = x + following
result
}
new FunIter[BigInt](BigInt(0), step)
}BigInt allows all Fibonacci numbers rather than a finite prefix before integer overflow. Replacing BigInt by Int gives the source's suggested machine-integer interface with that limitation. With the FunIter implementation from part (c), each transition runs once per generated cell, and copied iterators can advance independently while sharing the privately owned generator. A simpler alternative uses a pure function on pairs, , and projects the first component; the closure above follows the source's suggested single-value approach directly.Interpret After calls to
step as a positive increment, consistent with the increasing sequence and exclusive upper bound. State this precondition explicitly; a zero increment would not define the intended finite progression. Use a wider cursor to avoid integer overflow on the update after the last valid Int result.class RangeIter(lower: Int, upper: Int, step: Int) extends Iter[Int] {
require(step > 0)
private var current = lower.toLong
def hasNext: Boolean = current < upper.toLong
def next(): Int = {
require(hasNext)
val answer = current.toInt
current += step.toLong
answer
}
}next, the abstraction function is the sequence of values with , in increasing order. Repeated calls to hasNext do not change it; next removes precisely its first value. ThereforeIf lower >= upper, the represented sequence is empty immediately. The paper does not specify a descending-range convention; this implementation exposes its positive-step precondition rather than assigning one implicitly.Use the iterator adapter from part (b) with a primality test by trial division. A composite positive integer has a divisor no greater than its square root.Before each trial division iteration, no integer in divides
def primeIter(upperBound: Int): Iter[Int] = {
def isPrime(n: Int): Boolean = {
if (n < 2) false
else {
var d = 2
while (d <= n / d && n % d != 0) d += 1
d > n / d
}
}
filterIter[Int](isPrime _, new RangeIter(2, upperBound, 1))
}n. If division succeeds, the condition becomes false with , and isPrime returns false. Otherwise the loop ends with , so every possible small divisor has been excluded. The quotient comparison is equivalent to for positive values and avoids integer overflow in d*d.Bounds at most two give an empty iterator. This method tests candidates lazily and uses trial divisions for candidate ; no efficiency requirement in the question forces a sieve of Eratosthenes implementation.For The first is a discrete uniform distribution; the second is a Bernoulli distribution on Boolean values. Their exact mathematical probability mass functions areEach support contains exactly the positive-probability outcomes once, and the probabilities sum to one.
Uniform, require a nonempty integer interval. Compute its size in Long before converting to Double, avoiding integer overflow in u-l+1. For Flip, require , and omit zero-probability outcomes from the reported support.class Uniform(l: Int, u: Int) extends FiniteDist[Int] {
require(l <= u)
private val size = u.toLong - l.toLong + 1L
def getDom: List[Int] = {
val result = List.newBuilder[Int]
var x = l.toLong
while (x <= u.toLong) { result += x.toInt; x += 1L }
result.result()
}
def getProb(x: Int): Double =
if (l <= x && x <= u) 1.0 / size.toDouble else 0.0
}
class Flip(p: Double) extends FiniteDist[Boolean] {
require(0.0 <= p && p <= 1.0)
def getDom: List[Boolean] =
if (p == 0.0) List(false)
else if (p == 1.0) List(true)
else List(true, false)
def getProb(x: Boolean): Double = if (x) p else 1.0-p
}Double approximates these exact values by floating-point arithmetic. Materializing a huge support is limited by available memory; the Long calculation keeps its cardinality and endpoints arithmetically correct.