# Angles and fixed-point arithmetic

Apache's renderer uses a full unsigned 32-bit turn: `0x40000000` is 90 degrees, `0x80000000` is 180 degrees, and addition wraps at one revolution. Model matrices use signed Q31 components. Terrain and object positions use integers; the realistic helicopter model works in floating point and converts its results for the renderer.

## Trigonometry files

The game loads four little-endian tables. If they are absent, `initialise_trig_tables_` generates and saves them. Running that original generation path produces exactly the supplied files: **30,724 entries, no differences**. The reference harness intercepts the save boundary, so it never rewrites the installation.

| File | Entries | Input | Stored output |
| --- | ---: | --- | --- |
| SINCOS.TBL | 10,241 | `i / 8192` turns | `sin(angle) × (2³¹−1)` |
| ARCSIN.TBL | 8,193 | `i / 8192` | angle scaled to `2³²−1` per turn |
| ARCCOS.TBL | 8,193 | `i / 8192` | angle scaled to `2³²−1` per turn |
| ARCTAN.TBL | 4,097 | `i / 4096` | angle scaled to `2³²−1` per turn |

The sine file contains a complete revolution plus another quarter, including the last endpoint. Cosine reads the same storage with a quarter-turn offset. Matrix construction rounds a 32-bit angle to the nearest of 8,192 samples, giving steps of **0.0439453125 degrees**. The inverse functions recover signs and quadrants around their positive-domain tables.

The generator uses `6.28318530718` for a full turn in radians and `0.15915494309188485` for its reciprocal. Floating results are truncated toward zero. Against mathematical sine, the largest stored sine error is about 1.000082 integer units, or `4.657 × 10⁻¹⁰` after normalisation. This is the table-value error; the larger visual limitation is sampling the input angle in finite steps. The inverse tables have a maximum difference of about one stored angular unit.

`tools/math_tables.py` records every file hash, the largest mathematical error, its index and the comparison with original execution in [tables.json](tables.json).

## Multiplication and conversion

A typical Q31 product is formed with a signed 32×32 multiply, then shifted and rounded using the next bit. For an exact signed product `p`, the result is `(p + 2³⁰) >> 31`. The positive half-way bias matters when translating negative products; rounding an absolute magnitude and restoring its sign is not equivalent.

The Watcom helper `__CHP` temporarily changes the x87 rounding mode to truncation, runs `FRNDINT`, and restores the control word. It leaves the rounded value on the floating-point stack. This helper appears throughout the physics and instrument code before integer stores. It does not return an ordinary integer in EAX.

The flight model also uses x87 sine, cosine and tangent directly. The renderer's table quantisation should not be applied to those calculations.
