[HN Gopher] Avoiding Trigonometry (2013)
___________________________________________________________________
Avoiding Trigonometry (2013)
Author : WithinReason
Score : 201 points
Date : 2026-03-12 09:06 UTC (13 hours ago)
(HTM) web link (iquilezles.org)
(TXT) w3m dump (iquilezles.org)
| srean wrote:
| This has been some sort of a mix of peeve and a moment of
| enlightenment of mine when I understood this.
|
| 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.
| chriswarbo wrote:
| Norman Wildberger takes this to the extreme with Rational
| Trigonometry
| https://en.wikipedia.org/wiki/Divine_Proportions:_Rational_T...
|
| 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 wrote:
| He maybe considered contrarian but his math is sound.
| zzless wrote:
| With all due respect, no, it isn't. His drivel against set
| theory shows that he didn't even read the basic axiomatic set
| theory texts. In one of his papers, he is ranting against the
| axiom of infinity saying that 'there exists an infinite set'
| is not a precise mathematical statement. However, the axiom
| of infinity does not say any such thing! It precisely states
| the existence of some object than can be thought of as
| infinite but does not assign any semantics to it. Ironically,
| if he looked deeper, he would realize that the most
| interesting set theoretic proofs (independence results) are
| really the results in basic arithmetic (although covered in a
| lot of abstractions) and thus no less 'constructive' than his
| rational trigonometry.
| srean wrote:
| "Sound" means free of contradiction with respect to the
| axioms assumed.
|
| If you can derive a contradiction using his methods of
| computation I would study that with interest.
|
| By "sound" I do not mean provably sound. I mean I have not
| seen a proof of unsoundness yet.
| fn-mote wrote:
| To clarify:
|
| "Sound" != proof of soundness in the same way that the
| Riemann Hypothesis being true is not the same as RH being
| proven.
| srean wrote:
| Not a bad analogy. Damn good.
| kstrauser wrote:
| > "Sound" means free of contradiction with respect to the
| axioms assumed.
|
| Godel wept.
| sublinear wrote:
| > It precisely states the existence of some object than can
| be thought of as infinite but does not assign any semantics
| to it
|
| 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).
| lich_king wrote:
| Almost every critique of the axiom of infinity is
| philosophical. I don't think you can just say "the axiom is
| sound, so what's your point". And you don't even get to
| claim that because of Godel's incompleteness theorem.
|
| The axioms were not handed to us from above. They were a
| product of a thought process anchored to intuition about
| the real world. The outcomes of that process can be argued
| about. This includes the belief that the outcomes are wrong
| even if we can't point to any obvious paradox.
| Razengan wrote:
| Stuff like this is what really interests me in trying to
| imagine how differently aliens might use things that we
| consider to be immutable fundamentals.
| ajkjk wrote:
| personal theory: I think there's going to turn out to be a
| parallel development of math that is basically strictly
| finitist and never contends with the concept of an infinite
| set, much less the axiom of choice or any of its ilk. Which
| would require the foundation being something other than set
| theory. You basically do away with referring to the real
| numbers or the set of all natural numbers or anything like
| that, and skip all the parts of math that require them. I
| suspect that for any real-world purpose you basically don't
| lose anything. (This is a stance that I keep finding
| reinforced as a learn more math, but I don't really feel like
| I can defend it... it's a hunch I guess.)
| keeganpoppen wrote:
| he sounds awesome. even though i'm sure i would view him as a
| total kook, he's the kind of kook that life is brighter for
| everyone with his existence.
| storus wrote:
| In principle, wouldn't a change of basis be all that is needed?
| srean wrote:
| It's a little more than change of basis, although change of
| basis is an important part of it. It converts many apparently
| trigonometric operations into algebraic ones, root finding
| included.
|
| 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 wrote:
| This is just
| https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
| djmips wrote:
| This is avoiding an common but unnecesary round trip. When your
| inputs are vectors, angles are an unnecessary intermediate
| representation. You can substitute the geometric meaning of dot
| and cross product directly into the Rodrigues matrix and get by
| with less operations overall. It's more elegant, uses less
| instructions.
| skrebbel wrote:
| The point isn't that formula, it's that using angles for
| parameters or intermediary values is often wasteful.
| ajkjk wrote:
| It is not.
| djmips wrote:
| Also see https://fgiesen.wordpress.com/2010/10/21/finish-your-
| derivat...
| the__alchemist wrote:
| Ok, this is very interesting, as after pondering my code and
| the article's main pt, I independently came to the same
| conclusion that angles are what introduces trig. I agree that
| maybe people might be using angles as intermediates, but IMO
| there are cases where they're the most realistic abstraction.
| For example, how can I map a user's mouse movements, or button
| presses to a change in rotation without a scalar value? Without
| trig?
|
| 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?
| Karliss wrote:
| The article answers to this near the very beginning.
|
| > Now, don't get me wrong. Trigonometry is convenient and
| necessary for data input and for feeding the larger
| algorithm. What's wrong is when angles and trigonometry
| suddenly emerge deep in the internals of a 3D engine or
| algorithm out of nowhere.
|
| In most cases it is perfectly fine to store and clamp your
| first person view camera angles as angles (unless you are
| working on 6dof game). That's surface level input data not
| deep internals of 3d engine. You process your input, convert
| it to relevant vectors/matrices and only then you forget
| about angles. You will have at most few dozen such
| interactive inputs from user with well defined ranges and
| behavior. It's neither a problem from edge case handling
| perspective nor performance.
|
| The point isn't to avoid trig for the sake of avoiding it at
| all cost. It's about not introducing it in situations where
| it's unnecessary and redundant.
| the__alchemist wrote:
| Ah you're right! Then I believe the author and I are indeed
| on the same page.
| a_e_k wrote:
| My take as a graphics programmer is that angles are perfectly
| fine _as inputs_. Bring 'em! And we'll use the trig to turn
| those into matrices/quaternions/whatever to do the linear
| algebra. Not a problem.
|
| I'm a trig-avoider too, but see it more as about not wiggling
| back and forth. You don't want to be computing angle ->
| linear algebra -> angle -> linear algebra... (I.e., once
| you've computed derived values from angles, you can usually
| stay in the derived values realm.)
|
| Pro-tip I once learned from Eric Haines
| (https://erich.realtimerendering.com/) at a conference:
| angles should be represented in degrees until you have to
| convert them to radians to do the trig. That way, user-
| friendly angles like 90, 45, 30, 60, 180 are all exact and
| you can add and subtract and multiply them without floating-
| point drift. I.e., 90.0f is exactly representable in FP32,
| pi/2 is not. 1000 full revolutions of 360.0f degrees is
| exact, 1000 full revolutions of float(2*pi) is not.
| the__alchemist wrote:
| Hah. I think we're and the author of both articles on the
| same page about this. (I had to review my implementations
| to be sure). I'm a fan of all angles are radians for
| consistency, and it's more intuitive to me. I.e. a full rot
| is t. 1/2 rot is 1/2 t etc. Pi is standard but makes me do
| extra mental math, and degrees has the risk of mixing up
| units, and doesn't have that neat rotation mapping.
|
| Very good tip about the degrees mapping neatly to fp... I
| had not considered that in my reasoning.
| GistNoesis wrote:
| I think it boils down to the alternate view of rotations as two
| successive reflections.
|
| 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)
|
| [5]https://en.wikipedia.org/wiki/Geometric_algebra
|
| [6]https://en.wikipedia.org/wiki/Clifford_algebra
| DroneBetter wrote:
| citing the Wikipedia page for trigonometry makes this feel a
| lot like you just told an LLM the expected comment format and
| told it to write insightful comments
| GistNoesis wrote:
| I had to check the precise definition for trigonometry while
| writing my comment, found it interesting so I added a
| reference.
|
| As with many subject that we learn early in school, it's
| often interesting revisiting them as adult to perceive
| additional layer of depth by casting a new look.
|
| With trigonometry we tend to associate it with circle. But
| fundamentally it's the study of tri-angles.
|
| What is interesting is that the whole theory is "relative". I
| would reference the wikipedia page for angle but it may make
| me look like an LLM. The triangle doesn't have positions and
| orientation baked-in, what matters is the length of the sides
| and the angle between them.
|
| The theory by definition becomes translation and rotation
| invariant. And from this symmetry emerge the concept of
| rotations.
|
| What is also interesting about the concept of angle is that
| it is a scalar whereas the original objects like lines live
| in an higher dimension. To avoid losing information you
| therefore need multiple of these scalars to fully describe
| the scene.
|
| But there is a degree of redundancy because the angles of a
| triangle sums to pi. And from this degree of freedom results
| multiple paths to do the computations. But with this liberty
| comes the risks of not making progress and going in circles.
| Also it's harder to see if two points coming from different
| paths are the same or not, and that's why you have
| "identities".
|
| Often for doing the computation it's useful to break the
| symmetry, by picking a center, even though all points could
| be centers, (but you pick one and that has made all the
| difference).
|
| Similar situation arise in Elliptic Curve Cryptography, where
| all points could have the same role, but you pick one as your
| generator. Also in physics the concept of gauge invariance.
| the__alchemist wrote:
| I think this is more subjective than the author makes it out to
| be. I take a third approach: You can change out Matrices for
| Quaternions. Then do almost every operation using these two
| types, and a few operation between them. The operation
| implementations are a mix of dot products, quaternion
| multiplication, trig etc.
|
| 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)
| aleph_minus_one wrote:
| > You can change out Matrices for Quaternions.
|
| Better use spin groups: they work in every dimension.
| the__alchemist wrote:
| Hah! We can throw bivectors onto the pile too for the fans!
| the__alchemist wrote:
| Update with the big picture: I think the rotationAxisAngle
| example in the article is fine. The problem isn't that it
| exists and uses angles/trig: There are legit uses for that
| function! The problem is that it's not the best tool for
| aligning the spaceship. So: Problem is not that fn or
| angles/trig: It's using the wrong tool.
| dxuh wrote:
| I agree that use of trigonometry is almost always a smell, but
| e.g. in games there are so many cases where angles are just more
| useful and intuitive. I just grep-ed for "angle" in a game of
| mine and I find it for orienting billboard particles (esp. for
| particles a single angle is much better than a quat for example).
| Also for an FPS camera controller. It's much simpler to just
| store a pitch and a yaw and change that with mouse movement, than
| storing a quat. You can't really look at a quat and know what
| kind of rotation it represents without opening a calculator. And
| I also use it for angle "fudging" so if you want to interact with
| something if you are roughly looking at it, you need to configure
| an angle range that should be allowed. It just makes sense to
| configure this as an angle, because we have some intuition for
| angles. So I guess for computations angles are probably usually
| wrong, but they are great for intuition (they are low-dimensional
| and linear in amount of rotation). That makes them a better human
| interface for rotations. And as soon as you computations start
| with angles, of course they find their way into the rest of the
| code.
| eska wrote:
| _Now, don 't get me wrong. Trigonometry is convenient and
| necessary for data input and for feeding the larger algorithm._
| hrmtst93837 wrote:
| Storing pitch and yaw breaks down once you want arbitrary
| camera rolls, or if you need to interpolate between
| orientations, because of gimbal lock. Using angles for small UI
| bits or flat objects is fine, but when those billboard
| particles need more than one axis of freedom, you usually end
| up needing quats anyway. Quats are opaque, but conversion
| functions and debug views help when you actually need to read
| what's going on. Trig shortcuts mostly pay off for simple or
| highly constrained motion, but scaling them up tends to
| introduce messy edge cases.
| nananana9 wrote:
| I'd pretty much always store pitch/yaw for a first/third
| person controller. This makes it trivial to modify the values
| in response to input - `pitch += mouse_delta.y` and to clamp
| the pitch to a sane range (-90 to 90 deg) afterwards.
|
| 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 wrote:
| Interesting. I do it in quaternion, but mostly work in
| unclamped 6DOF systems.
| bob1029 wrote:
| Quaternions break down for other situations. They cannot
| represent a rotation greater than 360 degrees. In an engine
| like Unity (which stores rotation as quats), you can use
| arbitrary Euler angles in the editor and it will work fine,
| but the scene file has to store 2 things. There is an
| additional m_LocalEulerAnglesHint property that covers this
| edge case.
| the__alchemist wrote:
| You're right that quaternions don't work for those. Vec3 is
| the move IMO. Direction is axis; len is magnitude.
| 20k wrote:
| >poorly designed third party APIs
|
| 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 wrote:
| Based on my experience writing many games that work great
| barring the occasional random physics engine explosion, I
| suspect that trigonometry is responsible for a significant
| proportion of glitches.
|
| 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.
| xbar wrote:
| Your response is well-grounded--trig is trouble. Angles are
| often fine, but many 3rd party library functions are not.
|
| Have you ended up with a set of self-implemented tools that
| you reuse?
| waffletower wrote:
| You can definitely handle camera rotation via vector
| operations on rotation matrices.
| newsoftheday wrote:
| > I think this is missing the reason why these APIs are
| designed like this: because they're convenient and intuitive
|
| Agreed. In my view, the method the author figured out is far
| from intuitive for the general population, including me.
| ryandrake wrote:
| I guess the point is: How often do we _really_ need actual
| angles in the code? Probably only at the very ends: input
| from users and output to users. Everywhere else, we should
| just be treating them as sin /cos pairs or dot/cross pairs.
| So when the user inputs an angle, immediately convert it to
| what the computer actually needs, store it that way
| throughout the computation, and then only if/when the user
| needs to see an actual angle would you need to convert it
| back.
| simonreiff wrote:
| Nice article! I'm not a graphics programmer but mathematically it
| makes full sense that cross-product would be a vast optimization
| over using `sin()`. From a complexity perspective, the
| computation of a cross-product reduces to calculating a formal
| determinant, a fixed number of arithmetic operations, and hence
| resolves to O(1) complexity. By contrast, computing `sin()` is
| O(M(n)log(n)) (even though faster algorithms are often possible
| in practice). See Brent, Fast multiple-precision evaluation of
| elementary functions (1976).
| virgil_disgr4ce wrote:
| OK I have a genuine question outside the topic of TFA. Do people
| really prefer "orientate" over "orient"? This pattern baffles me.
| You don't get out of the subway and "orientate" yourself, you
| "orient" yourself.
|
| 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
| nyeah wrote:
| I think Americans tend to say "orient." I think English people
| tend to say "orientate."
| kevin_thibedeau wrote:
| I vote for "eastify".
| moi2388 wrote:
| I absolutely get out of the subway and orientate myself.
|
| If I orient myself I have not taken the subway but the orient
| express, I'm afraid..
| yobert wrote:
| When I get out of the subway, I always occident myself.
| cmovq wrote:
| For a graphics programmer acos(dot(x, y)) always raises an
| eyebrow. Since most of the time you actually want cos(theta) and
| even when you think you need the angle you probably don't.
| rprenger wrote:
| Also, while we're getting rid of angles, can we please get rid of
| cross products and just use geometric algebra tools?
| susmatthew wrote:
| I don't disagree with the "use linear algebra" assertion the
| author makes.
|
| The most impressive math I've seen done during a real-time
| technical conversation was by someone leveraging comprehensive
| command of trig identities.
| aap_ wrote:
| He's still computing cross(z, d) and dot(z, d) separately. that
| looks like a code smell to me. with quaternions this would be
| easier: just calculate the quotient between z and d and take the
| square root (which means adding 1 and renormalising). the square
| root is necessary if one is dealing with vectors, which live in a
| kind of square-y space. finding the rotation between two spinors
| is even simpler: it's just the quotient of the the spinors as
| quaternions. unfortunately hamilton's view that quaternions are
| the quotient of vectors has never been quite abandoned. it's much
| more natural to think of them as quotients of spinors.
| BenoitP wrote:
| > He's still computing cross(z, d) and dot(z, d) separately.
| that looks like a code smell to me. with quaternions ...
|
| Fair point, but I think you misspelled Projective Geometric
| Algebra
| aap_ wrote:
| If you only care about rotations in 3d, quaternions do
| everything you need :) with all the added benefits of having
| a division algebra to play with (after all the cross product
| is a division-algebraic operation). PGA is absolutely great,
| but quite a bit more complex mathematically, and its spinors
| are not as obvious as quaternionic ones. in addition GA is
| commonly taught in a very vector-brained way, but i find
| spinors much easier to deal with.
| ajkjk wrote:
| the dot/cross product are the same operation but expanded into
| coordinates. Maybe the quaternion (/geometric algebra) version
| is more compact but it's not like it's a different set of
| computations. Whereas their removal of the trig functions
| actually does skip a bunch of unnecessary steps.
___________________________________________________________________
(page generated 2026-03-12 23:01 UTC)