feature: asin/acos/atan inverse trig builtins#313
Merged
Conversation
Register Asin/Acos/Atan in the Builtin enum, name+tag tables, and the verifier's signature table. Wire the tree interpreter's unary-math arm to dispatch to Rust's f64::asin/acos/atan. atan2 already lived as a 2-arg builtin; this completes the inverse-trig set so geospatial code doesn't need a hand-rolled 6-term Taylor series.
New opcodes 171/172/173 routed through the existing unary-math dispatch arm. The compiler emits them from the asin/acos/atan builtins, mirroring sin/cos/tan. Cranelift JIT helpers (jit_asin, jit_acos, jit_atan) follow the same NaN-on-non-number pattern as jit_sin/jit_cos.
Declare the three new helper FuncIds and symbol registrations in both the in-process JIT and the AOT module. Extend the unary-math arm so OP_ASIN/OP_ACOS/OP_ATAN call into helpers.asin/acos/atan, and add the opcodes to the num-result tracker so downstream f64-typed reads pick up the result without a redundant bitcast.
Sixteen cross-engine assertions exercise asin/acos/atan on identity points (0, 1, +/-0.5, sqrt(3)), the three sin/cos/tan round-trips, and asin's NaN-on-out-of-domain behaviour. The haversine example computes London to Paris in one line of ilo using real asin, no Taylor stub, and runs through tests/examples_engines.rs across every engine.
Add the three inverse trig builtins to the Math table in SPEC.md, the compact builtin block in ai.txt, and the transcendental list plus builtin grid in skills/ilo/SKILL.md. Wording calls out radian ranges and the NaN-out-of-domain behaviour for asin and acos so agents don't need to retry on the first try.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
danieljohnmorris
added a commit
that referenced
this pull request
May 16, 2026
#313 (inverse-trig: OP_ASIN=171, OP_ACOS=172, OP_ATAN=173) and #314 (flat-cross-engine: OP_FLAT=171) both landed without rebasing one onto the other, so the merged main has two opcodes sharing value 171. Clippy's exhaustive-pattern checks catch it as "unreachable pattern" because the inverse-trig match arm matches all relevant values before OP_FLAT's arm gets a chance. Renumbering OP_FLAT to 174 (the next free slot after OP_ATAN=173) restores a unique mapping. No semantic change beyond the byte value, and bytecode is in-process so there's no compatibility concern.
danieljohnmorris
added a commit
that referenced
this pull request
May 16, 2026
twelve fixes since 0.11.3, surfaced by rerun4 personas plus standing asks: srt-Cranelift TLS desync (#306), CLI auto-run restoration (#307), OP_LISTAPPEND O(n^2) JIT memory regression (#308), precedence-pair hint false-positive on parens (#309), prefix ?? accepts call expression (#310), += pure-shape docs (#311), bare-mutation silent no-op verifier warning ILO-T033 (#312), asin/acos/atan inverse trig builtins (#313), flat cross-engine (#314), cond{~v} discard hint multi-stmt false-positive (#315), rsrt fn xs key-fn overloads (#316), xs.(expr) paren-after-dot diagnostic hint (#317).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Geospatial personas (gis-analyst rerun4) keep hand-rolling a 6-term Taylor series for
asinbecause the language shipssin/cos/tan/atan2but no inverse trig. That's a token tax on every haversine and bearing computation, and a silent precision footgun. Rust'sf64already hasasin,acos,atannatively, so the fix is plumbing across the three engines.Manifesto framing: builtins are dedicated opcodes, so adding them removes Taylor expansions from agent output forever and saves tokens every time someone reaches for great-circle distance.
Repro
Before:
After:
hav 51.5074 -0.1278 48.8566 2.3522returns343.55606034104164on all engines.What's in the diff
add asin/acos/atan inverse trig builtins (tree interpreter): registers the variants and wires the tree interpreter.vm: add OP_ASIN/OP_ACOS/OP_ATAN and jit_* helper externs: new opcodes 171/172/173 + JIT helper functions following the existing NaN-on-non-number pattern.cranelift: wire asin/acos/atan helpers in JIT and AOT codegen: declares the FuncIds, registers the symbols, extends the unary-math arm in both JIT and AOT paths.test: cross-engine regression + haversine example for inverse trig: 16 cross-engine assertions intests/regression_inverse_trig.rsplusexamples/inverse-trig-haversine.ilowhichtests/examples_engines.rsruns end-to-end.docs: document asin/acos/atan in spec, ai.txt and SKILL.md: keeps the four canonical docs in sync.Test plan
cargo test --release --features cranelift --test regression_inverse_trig— 16 passedcargo test --release --features cranelift --test examples_engines— haversine example passes on tree + vmcargo test --release --features craneliftfull suite green locally (the only failures werelibilo.alookups that resolve when the static lib is intarget/release/; CI builds at that path)cargo fmt --checkcargo clippy --release --features cranelift --all-targets -- -D warningsFollow-ups
None blocking. Worth considering whether to also expose
pias a constant so*180 /x pireads cleanly without the magic 0.0174... literal, but that's a separate ask.