Hacker News
Avoiding Trigonometry (2013)
chriswarbo
|next
[-]
It eschews angles entirely, sticking to ratios. It avoids square roots by sticking to "quadrances" (squared distance; i.e. pythagoras/euclidean-distance without taking square roots).
I highly recommend Wildberger's extensive Youtube channels too https://www.youtube.com/@njwildberger and https://www.youtube.com/@WildEggmathematicscourses
He's quite contrarian, so I'd take his informal statements with a pinch of salt (e.g. that there's no such thing as Real numbers; the underlying argument is reasonable, but the grand statements lose all that nuance); but he ends up approaching many subjects from an interesting perspective, and presents lots of nice connections e.g. between projective geometry, linear algebra, etc.
srean
|root
|parent
[-]
zzless
|root
|parent
[-]
srean
|root
|parent
|next
[-]
If you can derive a contradiction using his methods of computation I would study that with interest.
By "sound" I do not mean probably sound. I mean I have not seen a proof of unsoundness yet.
sublinear
|root
|parent
|previous
[-]
Can you elaborate on this? I think many understand that the "existence of some object" implies there is some semantic difference even if there isn't a practical one.
I really enjoyed Wildberger's take back in high school and college. It can be far more intuitive to avoid unnecessary invocation of calculation and abstraction when possible.
I think the main thrust of his argument was that if we're going to give in to notions of infinity, irrationals, etc. it should be when they're truly needed. Most students are being given the opposite (as early as possible and with bad examples) to suit the limited time given in school. He then asks if/where we really need them at all, and has yet to be answered convincingly enough (probably only because nobody cares).
srean
|next
|previous
[-]
I wholeheartedly agree with the point being made in the post. I had commented about this in the recent asin() post but deleted thinking it might not be of general interest.
If you care about angles and rotations in the plane, it is often profitable to represent an angle not by a scalar such as a degree or a radian but as a tuple
(cos \theta, sin \theta)
or as a complex number.This way one can often avoid calls to expensive trigonometric functions. One may need calls to square roots and general polynomial root finding.
In Python you can represent an angle as a unit complex numbers and the runtime will do the computations for you.
For example, if you needed the angular bisector of an angle subtended at the origin (you can translate the vertex there and later undo the translation), the bisector is just the geometric mean of the arms of the angle
sqrt(z1 * z2)
Along with stereographic transform and its inverse you can do a lot.This is directly related to the field of algebraic numbers.
With complex numbers you get translations, scaled rotations and reflections. Sufficient for Euclidean geometry.
20k
|next
|previous
[-]
I think this is missing the reason why these APIs are designed like this: because they're convenient and intuitive
Its rare that this kind of performance matters, or that the minor imprecisions of this kind of code matter at all. While its certainly true that we can write a better composite function, it also means that.. we have to write a completely new function for it
Breaking things up into simple, easy to understand, reusable representations is good. The complex part about this kinds of maths is not the code, its breaking up what you're trying to do into a set of abstracted concepts so that it doesn't turn into a maintenance nightmare
Where this really shows up more obviously is in more real-world library: axis angle rotations are probably a strong type with a lot of useful functions attached to it, to make your life easier. For maths there is always an abstraction penalty, but its usually worth the time saved, because 99.9999% of the time it simply doesn't matter
Add on top of this that this code would be optimised away with -ffast-math, and its not really relevant most of the time. I think everyone goes through this period when they think "lots of this trig is redundant, oh no!", but the software engineering takes priority generally
et1337
|root
|parent
[-]
I think over the years I subconsciously learned to avoid trig because of the issues mentioned, but I do still fall back to angles, especially for things like camera rotation. I am curious how far the OP goes with this crusade in their production code.
GistNoesis
|next
|previous
[-]
You can then use householder matrix to avoid trigonometry.
These geometric math tricks are sometimes useful for efficient computations.
For example you can improve Vector-Quantization Variational AutoEncoder (VQ-VAE) using a rotation trick, and compute it efficiently without trigonometry using Householder matrix to find the optimal rotation which map one vector to the other. See section 4.2 of [1]
The question why would someone avoid trigonometry instead of looking toward it is another one. Trigonometry [2] is related to the study of the triangles and connect it naturally to the notion of rotation.
Rotations [3] are a very rich concept related to exponentiation (Multiplication is repeated addition, Exponentiation is repeated multiplication).
As doing things repeatedly tend to diverge, rotations are self stabilizing, which makes them good candidates as building blocks for the universe [4].
Because those operations are non commutative, tremendous complexity emerge just from the order in which the simple operations are repeated, yet it's stable by construction [5][6]
[0]https://en.wikipedia.org/wiki/Householder_transformation
[1]https://arxiv.org/abs/2410.06424
[2]https://en.wikipedia.org/wiki/Trigonometry
[3]https://en.wikipedia.org/wiki/Matrix_exponential
[4]https://en.wikipedia.org/wiki/Exponential_map_(Lie_theory)
djmips
|next
|previous
[-]
the__alchemist
|root
|parent
[-]
User moves cursor or stick a number of pixels/units. User holds key for a number of ms. This is a scalar: An integer or floating point. I pose this to the trig-avoiders: How do I introduce a scalar value into a system of vectors and matrices or quaternions?
dxuh
|next
|previous
[-]
hrmtst93837
|root
|parent
|next
[-]
bob1029
|root
|parent
|next
[-]
nananana9
|root
|parent
|previous
[-]
You can then calculate a quaternion from the pitch/yaw and do whatever additional transforms you wish (e.g. temporary rotation for recoil, or roll when peeking around a corner).
the__alchemist
|next
|previous
[-]
I find this flow works well because it's like building arbitrarily complex transformation by composing a few operations, so easy to keep in my head. Or maybe I just got used to it, and the key is find a stick with a pattern you're effective with.
So:
> For example, you are aligning a spaceship to an animation path, by making sure the spaceship's z axis aligns with the path's tangent or direction vector d.
Might be:
let ship_z = ship.orientation.rotate_vec(Z_AXIS);
let rotator = Quaternion::from_unit_vecs(ship_z.to_normalized(), path.to_normalized());
ship.orientation *= rotator;
I should break this down into individual interoperations to compare this to the two examples in the article. To start, `from_unit_vecs` is based on the cross product, and `rotate_vec` is based on quaternion-vector multiplication. So no trig there. But `quaternion::from_axis_angle()` uses sin and cos.I need to review for the sort of redundant operations it warns about, but from a skim, I'm only using acos for SLERP, and computing dihedral angles, which aren't really the basic building blocks. Not using atan. So maybe OK?
edit: Insight: It appears the use of trig in my code is exclusively for when an angle is part of the concept. If something is only vectors and quaternions, it stays that way. If an angle is introduced, trig occurs. And to the article: For that spaceship alignment example, it doesn't introduce an angle, so no trig. But there are many cases IMO where you want an explicit angle (Think user interactions)
the__alchemist
|root
|parent
|next
[-]
simonreiff
|next
|previous
[-]
storus
|next
|previous
[-]
srean
|root
|parent
[-]
There are certain drawbacks. If the solution involves non-algebraic numbers there is no getting away from the transcendental numbers (that ultimately get approximated by algebraic numbers).
xeonmc
|next
|previous
[-]
djmips
|root
|parent
|next
[-]
virgil_disgr4ce
|next
|previous
[-]
I mean I'm perfectly aware that language is a descriptive cultural process etc etc but man this bugs the crap out of me for some reason
ozgurozkan
|previous
[-]
We ran into an analogous situation building audn.ai (https://audn.ai), an AI red-teaming platform. The naive approach to finding behavioral vulnerabilities in AI agents is to enumerate attack prompts — essentially computing "angles" by hand. But the real geometric primitive is adversarial pressure: you want a system that directly produces the failure modes without an acos/cos detour through human-crafted prompt lists.
So we built an autonomous Red Team AI (powered by our Pingu Unchained LLM) that generates and runs adversarial simulations in a closed RL loop with a Blue Team that patches defenses in real time. The result — millions of attack vectors without the manual enumeration step — feels a bit like replacing rotationAxisAngle(acos(dot(z,d))) with a direct cross/dot formulation. The "angle" abstraction just falls away.
Anyway, great article. The principle that elegance usually signals you've found the right representation applies pretty broadly.