CERN openlab · Project note
Making precision a setting I could test
In early July I wanted to answer a deceptively small question about PEPPER. If I asked the generator to calculate with 32-bit numbers, which parts of the calculation would actually run in 32 bits? I started by making precision a choice I could build, record and repeat.
Four builds, two questions
I set up separate builds for ordinary single and double precision, called FP32 and FP64, and for each precision with CADNA on the CPU. The ordinary builds let me compare the arithmetic used by the generator. CADNA added a different kind of evidence. It varies the rounding across copies of a calculation and uses their spread to estimate how many digits remain stable. Comparing the four modes gave me a way to ask both whether an answer moved and where it became sensitive. CERN openlab project and talk · CADNA project.
A tiny example from C++
Take a variable x declared as a float. In x * 0.5, C++ treats 0.5 as a double, so the expression is evaluated as a double-precision expression at the language level. Write x * 0.5f and the expression has type float. Both expressions can give the same result in this example. The interesting bit is that the type of the variable and the type of the operation are two things to check. C++ floating-point literal rules.
That distinction mattered in the generator. I used a shared numerical type for the core calculations, then checked the places where other assumptions could creep back in, such as constants, mathematical functions and complex numbers. The diagnostic builds also needed an explicit conversion when passing values to libraries that expect ordinary floats. The numerical type tells me how a result was calculated. The storage type tells me how it was written.
By the time I could switch between builds, I had something much more useful than a collection of edited source files. I could say exactly which arithmetic I was testing and reproduce the setup when the next calculation surprised me.