Live data from Hacker News

Even faster asin() was staring right at me

16bpp.net

31–40 of 68 posts

Re: Even faster asin() was staring right at me

#31
I've been thinking about this since [1] the other day, but I still love how rotation by small angles lets you drop trig entirely.

Let α represent a roll rotation, and β a pitch rotation.

Let R(α) be:

    ( cos α   sin α   0)
    (-sin α   cos α   0)
    (   0       0     1)
Let R(β) be:

    (1     0       0   )
    (0   cos β   -sin β)
    (0   sin β    cos β)
Combine them:

    R(β).R(α) = (    cos α           sin α          0   )
                ((-sin α*cos β)   (cos α*cos β)   -sin β)
                ((-sin α*sin β)   (cos α*sin β)    cos β)
But! For small α and β, just approximate:

    ( 1   α   0)
    (-α   1  -β)
    ( 0   β   1)
So now:

    x' = x + αy
    y' = y - αx - βz
    z' = z + βy
[1]https://news.ycombinator.com/item?id=47348192

Re: Even faster asin() was staring right at me

#32
post #10

Earlier quoted context omitted.

yes, Estrin's method is the update

Sorry, I said that wrong. Estrin's doesn't reduce the number of multiplications.

If your goal is reducing the number of multiplications, I imagine it would make sense to factor that polynomial into degree-1 and degree-2 factors.

Re: Even faster asin() was staring right at me

#33
post #3

Earlier quoted context omitted.

On modern machines, looking things up can be slower than recomputing it, when the computation is simple. This is because the memory is much slower than the CPU, which means you can often compute something many times over before the answer from memory arrives.

It may be, especially when it comes to unnecessary cache. But I think `atan` is almost a brute force. Lookup is nothing comparing to that. Sin/cos must be borders of sqrt(x²+y²). It is also cached indeed.

> Sin/cos must be borders of sqrt(x²+y²). It is also cached indeed

This doesn't make a ton of sense.

Re: Even faster asin() was staring right at me

#34

I've been thinking about this since [1] the other day, but I still love how rotation by small angles lets you drop trig entirely. Let α represent a roll rotation, and β a pitch rotation. Let R(α) be: ( cos α sin α 0) (-sin α cos α 0) ( 0 0 1) Let R(β) be: (1 0 0 ) (0 cos β -sin β) (0 sin β cos β) Combine them: R(β).R(α) = ( cos α sin α 0 ) ((-sin α*cos β) (cos α*cos β) -sin β) ((-sin α*sin β) (cos α*sin β) cos β) But…

If you just see the conclusion I think it's hard to immediately grok how rotation can arise from this.

This is a great technique for cheaply doing 3D starfields etc on 8-bit machines.

Look ma, no sine table!

Re: Even faster asin() was staring right at me

#35

Earlier quoted context omitted.

>> It also gets in the way of elegance and truth. Where did that come from in the article?

I revisited that article and ... now I have no idea. Maybe I stumbled into some other trig-related article and came back here. Or maybe this one had some A/B content going on? The only thing I remember at this point is that I copied and pasted that sentence (I didn't type it.) Even search doesn't find the sentence anywhere but HN.

Search finds that sentence on this blog post https://iquilezles.org/articles/noacos/

Re: Even faster asin() was staring right at me

#36

I've been thinking about this since [1] the other day, but I still love how rotation by small angles lets you drop trig entirely. Let α represent a roll rotation, and β a pitch rotation. Let R(α) be: ( cos α sin α 0) (-sin α cos α 0) ( 0 0 1) Let R(β) be: (1 0 0 ) (0 cos β -sin β) (0 sin β cos β) Combine them: R(β).R(α) = ( cos α sin α 0 ) ((-sin α*cos β) (cos α*cos β) -sin β) ((-sin α*sin β) (cos α*sin β) cos β) But…

If you just see the conclusion I think it's hard to immediately grok how rotation can arise from this. This is a great technique for cheaply doing 3D starfields etc on 8-bit machines. Look ma, no sine table!

A related interesting fact is that small angular motions compose almost like vectors, order does not matter (i.e. they are commutative). This makes differential kinematics easier to deal with when dealing with polar or cylindrical coordinate systems.

Large angular deflections while being linear transforms, do not in general commute.

It will spoil the linear relation in your elegant expression, but a slightly better approximation for cos for small θ is

    1 - 0.5θ²

Re: Even faster asin() was staring right at me

#37

Earlier quoted context omitted.

I revisited that article and ... now I have no idea. Maybe I stumbled into some other trig-related article and came back here. Or maybe this one had some A/B content going on? The only thing I remember at this point is that I copied and pasted that sentence (I didn't type it.) Even search doesn't find the sentence anywhere but HN.

Search finds that sentence on this blog post https://iquilezles.org/articles/noacos/

Thanks for finding it! Still not sure how I got there while thinking I was at "Even Faster Asin()..."

Re: Even faster asin() was staring right at me

#38

I haven't kept up with C++ in a few years - what does constexpr do for local variables? constexpr double a0 = 1.5707288;

The compiler can substitute the value how it sees fit. It's like #define, but type-safe and scoped. Maybe it's folded into expressions, propagated through constant expressions, or used it in contexts that require compile-time constants (template parameters, array sizes, static_assert, other constexpr expressions). I mean, not in this case of pi/2, where it's more about announcing semantics, but in general those are t…

I'd like something like this in C or C++ quite honestly.

Something like a struct that I can say "this struct is global to the whole program and everyone can see it, but once this function exits those values are locked in". Maybe something like that one function is allowed to unlock and update it, but nowhere else.

Think in terms of storing a bunch of precomputed coefficients that are based on the samplerate of a system, where you really only need to set it up once on startup and it is unlikely to change during the application's running lifetime.

I feel like there probably is a way to do this, and if I was good at high level languages like C I'd know what it is. If you know, tell me what I'm not understanding ;-)

Re: Even faster asin() was staring right at me

#39

Earlier quoted context omitted.

It may be, especially when it comes to unnecessary cache. But I think `atan` is almost a brute force. Lookup is nothing comparing to that. Sin/cos must be borders of sqrt(x²+y²). It is also cached indeed.

> Sin/cos must be borders of sqrt(x²+y²). It is also cached indeed This doesn't make a ton of sense.

In what way do you think a sin function is computed? It is something that computed and cached in my opinion.

I think it is stored like sintable[deg]. The degree is index.

Re: Even faster asin() was staring right at me

#40
post #21
post #3

Earlier quoted context omitted.

On modern machines, looking things up can be slower than recomputing it, when the computation is simple. This is because the memory is much slower than the CPU, which means you can often compute something many times over before the answer from memory arrives.

Not just modern machines, the Nintendo64 was memory bound under most circumstances and as such many traditional optimizations (lookup tables, unrolling loops) can be slower on the N64. The unrolling loops case is interesting. Because the cpu has to fetch more instructions this puts more strain on the memory bus. If curious, On a N64 the graphics chip is also the memory controller so every thing the cpu can do to stay…

> This is also why the n64 has weird 9-bit ram, it is so they could use a 18-bit pixel format, only taking two bytes per pixel, for cpu requests the memory controller ignored the 9th bit, presenting a normal 8 bit byte.

The Ensoniq EPS sampler (the first version) used 13-bit RAM for sample memory. Why 13 and not 12? Who knows? Possibly because they wanted it "one louder", possibly because the Big Rival in the E-Mu Emulator series used μ-law codecs which have the same effective dynamic range as 13-bit linear.

Anyway you read a normal 16-bit word using the 68000's normal 16-bit instructions but only the upper 13 were actually valid data for the RAM, the rest were tied low. Haha, no code space for you!

Post reply on HN