Skip to content

community-projects

Claude Opus 5.5 cut PSP math tables from 4.9 MB to 10.5 KB

Claude News

The PSP's math unit plainly has no room for megabytes of lookup data, yet the PPSSPP emulator shipped 4.9 MB of correction tables to match its sine and reciprocal instructions exactly. As the PPSSPP blog reports, Claude Opus 5.5 spent about an hour working out the circuit underneath, and the replacement fits in 10.5 KB of coefficients, exact over every 32-bit input.

At a glance

  • Eight VFPU special functions, from reciprocal and square root to sine, arcsine and log2, now come from one quadratic interpolator model instead of tables dumped from a real PSP.
  • The key clue was neighbouring rcp segments sharing identical fitted values to four decimals, which exposed a single squarer unit used by every function and rounding t² up to a multiple of 256.
  • The new code is faster, with sin dropping from 14.6 ns to 5.9 ns, but outputs alone cannot show whether the final adder is shared with the vdot dot-product unit.

If you have not followed PPSSPP's accuracy work: the VFPU is the PSP's vector unit. It is a MIPS co-processor that shares the CPU's instruction stream but runs its own pipeline, and like a modern GPU it has a special function unit. None of its approximations return the correctly rounded IEEE result. Long-term contributor fp64 made them bit-exact by dumping full result tables from a real PSP and adding corrections on top of close approximations.

Plain curve fitting stalled at about 93% of outputs

The blog's author was encouraged by skmp's work reversing the Dreamcast's SH-4 FPU with three AI models. Claude used fp64's code as an exact oracle that runs in a second on a laptop. First, a new hardware test, pspautotests cpu/vfpu/exact, checked the oracle against a real PSP, and along the way it found a few mismatches in PPSSPP's other CPU backends. Checking a hypothesis against all 2^32 inputs took 30 seconds.

The obvious guess was a piecewise quadratic for each chunk of 1/x. It got about 93% of outputs exactly right, whatever the chunk size or degree. Float coefficients run through the VFPU's own dot product reached about 92%. Henrik suggested vdot as the building block, because on the Dreamcast the FIPR inner-product unit was reused by the function approximator. A single vdot also stalled at 92%.

The misses all looked alike: the best real-valued quadratic was off by about one 24-bit ulp, a unit in the last place. So Claude stopped fitting and asked a different question: could any set of coefficients reproduce every output exactly? Each output then becomes an interval constraint on the unknowns, and intervals intersect cheaply.

The top 7 bits of the mantissa pick one of 128 segments

Every run of 64 consecutive inputs turned out to be an exact straight line. Up to 1,024 of those intervals, or 2^16 inputs, share one slope, and 2,048 never do. So the top 7 mantissa bits pick one of 128 segments, and each segment's slope equals the true derivative at its centre.

Subtracting a smooth quadratic from the per-interval offsets left a sawtooth one ulp tall, the same in every function. Its climb matched the local slope of the squared term: −0.273 ulps per interval for rcp against a ramp of 0.28, and −0.151 for exp2 against 0.15. The squared term gets floored to whole ulps by itself, and least squares cannot see a floor like that.

Every model of that floor hit the same wall: 99.65% correct. Some of the dead ends were Claude's own bugs. One search stepped a coefficient too coarsely to ever hit the true value, one extraction subtracted a constant twice, and a zsh quirk made one sweep silently test nothing.

Rcp segments 115 to 120 all printed 143.9636

The breakthrough came from a coincidence in a sweep. Claude fitted each rcp segment on its own, and neighbouring segments showed identical best-fit squared coefficients to four decimals. Identical decimals meant identical integer data. The coefficients turned out to be multiples of 8/2^20, which makes each one a small integer n.

The integer sequences also matched across functions. Exp2's segment 32 equals rcp's segment 116, and rsqrt's segment 100 equals rcp's segment 54, so one squarer serves them all. With 109 distinct values of n, Claude solved for the squarer's output directly. The squarer rounds t² up to a multiple of 256, and that matched every value of n and t with zero mismatches.

All 512 segments of rcp, rsqrt, sqrt and exp2 then fit. The resulting code matched fp64's on the first run across all 2^32 inputs, apart from one bug in the wrapper arithmetic.

Sin counts backwards and log2 trims its own coefficients

Sin fit at no segment size until Claude looked at where its outputs step the wrong way. For rcp those steps fall between inputs 64k + 63 and 64k + 64; for sin they come one input later. The hardware indexes the quarter wave from the other end, with y = 2^23 − x, so it computes sin as the cosine of the complementary angle. Asin confirmed the binade rule from the other side: 1.25% of its outputs keep 23 significant bits instead of 22.

Log2 fit at once for inputs in [1, 4) and failed everywhere else. The datapath cuts its coefficients down to the output's precision. At level d, the slope loses its low d + 2 bits and the squared coefficient loses its low d bits. For negative exponents, level 7 with a step of 2^-15, the squared term disappears completely.

A 10.5 KB interpolator runs sin in 5.9 ns instead of 14.6 ns

The circuit is a textbook one from the hardware literature, close to the minimax quadratic interpolator of Piñeiro, Oberman, Muller and Bruguera, or NVIDIA's multifunction interpolator (Oberman and Siu, 2005). Each function has a 128-entry ROM, and a shared squarer sees only the top 10 bits of the offset. Think of a printed table with a correction column: look up the nearest row, then nudge by distance plus a small bend.

The new code is also faster than the tables: rcp goes from 4.2 ns to 3.6 ns, rsqrt from 5.4 to 3.6, exp2 from 6.3 to 3.9, log2 from 7.1 to 5.1, and asin from 6.0 to 3.6. Vrot needs sine and cosine together, and sharing the argument reduction makes the pair about 10% faster. PPSSPP will enable accurate emulation by default.

The post is candid about its limit. Whether the final adder is shared with vdot, as on the Dreamcast, cannot be told from outputs alone, although the separately truncated products are compatible with that. In our view, the one-hour figure undersells what the work relied on: without fp64's oracle, checked against real hardware, there would have been nothing to test 2^32 inputs against.

When the 4.9 MB of tables go

The pull request is titled "VFPU: Replace fp64's correction tables with accurate implementation of special functions". According to the post, future PPSSPP versions will save a few megabytes of shipped tables and turn accurate emulation of these functions on by default. The post names no version number or release date. The question of a shared adder stays open, because outputs alone cannot settle it.

Related stories

  1. Claude's cipher project writes off the gold bar codes
  2. Claude Fable knocked 20 bits off most popular hashes
  3. Claude's raw thinking never leaves the server
  4. Claude stamps 2026 onto "best X" search queries
  5. WMTrace won't ship an Anthropic watermark detector
  6. Sonnet 5 keeps telling testers it's GPT-4

Comments

No comments yet. Be the first.

Join the conversation

Sign in with Google to leave a comment. Your name and avatar come from your Google profile, and the comment appears after moderation.

We only use your name and avatar from Google. We never store your email address.