## A.1 Main Include File

The `core/pbrt.h` file is included by all other source files in the
system. It contains all global function declarations and inline functions,
a few macros and numeric constants, and other globally accessible data.
All files that include `pbrt.h` get a number of other included header
files from `pbrt.h`. This simplifies creation of new source files,
almost all of which will want access to these extra headers. However, in
the interest of compile time efficiency, we keep the number of these
automatically included files to a minimum; the ones here are necessary for
almost all modules.

Almost all floating-point values in `pbrt` are declared as
`Float`s. (The only exception is a few cases where
a 32-bit `float` or a 64-bit `double` is specifically needed
(e.g., when saving binary values to files). Whether a `Float` is
actually a `float` or a `double` is determined at compile time
with the `PBRT_FLOAT_AS_DOUBLE` macro; this makes it possible to
build versions of `pbrt` using either representation. 32-bit `float`s
almost always have sufficient precision for ray tracing, but it’s helpful
to be able to switch to `double` for numerically tricky situations as
well as to verify that rounding error with `float`s isn’t causing
errors for a given scene.

#### Clamping

`Clamp()` clamps the given value `val` to lie between the values
`low` and `high`. For convenience `Clamp()` allows the
types of the values giving the extent to be different than the type being
clamped (but its implementation requires that implicit conversion is legal
to the type being clamped). By being implemented this way, the
implementation allows calls like `Clamp(floatValue, 0, 1)` which would
otherwise be disallowed by C++’s template type resolution rules.

#### Modulus

`Mod()` computes the remainder of . `pbrt` has its own version of
this (rather than using `%`) in order to provide the behavior that
the modulus of a negative number is always positive or zero. Starting with C++11,
the behavior of `%` has been specified to return a negative value or
zero in this case, so that the identity `(a/b)*b + a%b == a` holds.

A specialization for
`Float`s calls out to the corresponding standard library function.

#### Useful Constants

A number of constants, most of them related to , are used enough that it’s worth having them easily available.

#### Converting between Angle Measures

Two simple functions convert from angles expressed in degrees to radians, and vice versa:

#### Base-2 Operations

Because the math library doesn’t provide a base-2 logarithm function, we provide one here, using the identity .

It’s also useful to be able to compute an integer base-2 logarithm. Rather than computing an (expensive) floating-point logarithm and converting to an integer, it’s much more efficient to count the number of leading zeros up to the first one in the 32-bit binary representation of the value and then subtract this value from 31, which gives the index of the first bit set, which is in turn the integer base-2 logarithm. (This efficiency comes in part from the fact that most CPUs have an instruction to count these zeros.)

The code here uses the `__builtin_clz()` intrinsic, which is
available in the `g++` and `clang` compilers;
`_BitScanReverse()` is used to implement similar functionality with
MSVC in code that isn’t shown here.

There are clever tricks that can be used to efficiently determine if a given integer is an exact power of 2, or round an integer up to the next higher (or equal) power of 2. (It’s worthwhile to take a minute and work through for yourself how these two functions work.)

A variant of `RoundUpPow2()` for `int64_t` is also provided but
isn’t included in the text here.

Some of the low-discrepancy sampling code in
Chapter 7 needs to efficiently count the
number of trailing zeros in the binary representation of a value;
`CountTrailingZeros()` is a wrapper around a compiler-specific
intrinsic that maps to a single instruction on most architectures.

#### Interval Search

`FindInterval()` is a helper function that emulates the behavior of
`std::upper_bound()`, but uses a function object to get values at various
indices instead of requiring access to an actual array. This way, it
becomes possible to bisect arrays that are procedurally generated, such as
those interpolated from point samples. The implementation here
also adds some bounds checking for corner cases (e.g., making sure
that a valid interval is selected even in the case the predicate evaluates
to `true` or `false` for all entries), which would normally have
to follow a call to `std::upper_bound()`.

`pred`at

`middle`>>

`pred`at

`middle`>>=

### A.1.2 Pseudo-Random Numbers

`pbrt` uses an implementation of the PCG pseudo-random number generator
(O’Neill 2014) to generate pseudo-random numbers. This generator is one of
the best random number generators currently known. Not only does it pass a
variety of rigorous statistical tests that have been the bane of earlier
pseudo-random number generators, but its implementation is also extremely
efficient.

We wrap its implementation in a small random number generator class,
`RNG`. Doing so allows us to use it with slightly
less verbose calls throughout the rest of the system. Random number
generator implementation is an esoteric art; therefore, we will not include
or discuss the implementation here but will describe the APIs provided.

The `RNG` class provides two constructors. The first, which takes no
arguments, sets the internal state to reasonable defaults. The second
takes a single argument that selects a sequence of pseudo-random values.

The PCG random number generator actually allows the user to provide two 64-bit values to configure its operation: one chooses from one of different sequences of random numbers, while the second effectively selects a starting point within such a sequence. Many pseudo-random number generators only allow this second form of configuration, which alone isn’t as good: having independent non-overlapping sequences of values rather than different starting points in a single sequence provides greater non-uniformity in the generated values.

For `pbrt`’s needs, selecting different sequences is sufficient, so the
`RNG` implementation doesn’t provide a mechanism to also select the
starting point within a sequence.

`RNG`s shouldn’t be used in `pbrt` without either providing an initial
sequence index via the constructor or a call to the `SetSequence()`
method; otherwise there’s risk that different parts of the system will
inadvertently use correlated sequences of pseudo-random values, which in
turn could cause surprising errors.

There are two variants of the `UniformUInt32()` method. The first
returns a pseudo-random number in the range .

The second returns a value uniformly distributed in the range given a bound . The last two versions of `pbrt` effectively used
`UniformUInt32() % b` for this second computation. That approach
is subtly flawed—in the case that `b` doesn’t evenly divide
, then there is higher probability of choosing any given value in
the sub-range .

The implementation here first computes the above remainder
efficiently using only 32 bit arithmetic and stores it in the variable
`threshold`. Then, if the pseudo-random value returned by
`UniformUInt32()` is less than `threshold`,
it is discarded and a
new value is generated. The resulting distribution of values has a uniform
distribution after the modulus operation, giving a uniformly distributed sample value.

`UniformFloat()` generates a pseudo-random floating-point number in the
half-open interval .