Live data from Hacker News

Implementing Cosine in C from Scratch (2020)

austinhenley.com

41–50 of 139 posts

Re: Implementing Cosine in C from Scratch (2020)

#41
post #22

Earlier quoted context omitted.

> You can also memorize with an LRU cache. That's probably not going to perform well for an operation this fast. The computation is faster than main memory read.

You can fit quite a large LRU cache in the L2 cache of the processor. You never want to go to main memory for a lerp table.

In some cases (eg. oldskool 2D graphics) a 256-entry LUT is enough. And a 8-bit fixed point format can be enough so the whole table fits in 256 bytes.

Re: Implementing Cosine in C from Scratch (2020)

#42
post #15

Earlier quoted context omitted.

https://github.com/ifduyue/musl/blob/master/src/math/__cos.c

> Input y is the tail of x. What does "tail" mean in this context?

It is a double-double representation [1], where a logical fp number is represented with a sum of two machine fp numbers x (head, larger) and y (tail, smaller). This effectively doubles the mantissa. In the context of musl this representation is produced from the range reduction process [2].

[1] https://en.wikipedia.org/wiki/Quadruple-precision_floating-p...

[2] https://github.com/ifduyue/musl/blob/6d8a515796270eb6cec8a27...

Re: Implementing Cosine in C from Scratch (2020)

#43
post #7

I learned how to write programs from Scratch[0]. Back in the pre-1.4 days (IIRC) there was no native sin/cos functions, so they had to be "implemented" somehow to translate arbitrary angles into delta (x,y). The way that I found people did this was as follows (for sin(A), cos(A)): Invisible sprite: [ when I receive "sine" ]: [ go to center ] [ turn A degrees ] [ move 1 step forward ] Now, anyone that wants to know si…

I guess scratch (or LOGO) is Turing complete, so someone could make a CPU built using a little turtle in a box where all functionality is built out of LOGO commands.

Re: Implementing Cosine in C from Scratch (2020)

#44
post #12

The implementation of the __cos kernel in Musl is actually quite elegant. After reducing the input to the range [-pi/4, pi/4], it just applies the best degree-14 polynomial for approximating the cosine on this interval. It turns out that this suffices for having an error that is less than the machine precision. The coefficients of this polynomial can be computed with the Remez algorithm, but even truncating the Cheby…

This has been the standard algorithm used by every libm for decades. Its not special to Musl.

Re: Implementing Cosine in C from Scratch (2020)

#45

Earlier quoted context omitted.

> Input y is the tail of x. What does "tail" mean in this context?

It is a double-double representation [1], where a logical fp number is represented with a sum of two machine fp numbers x (head, larger) and y (tail, smaller). This effectively doubles the mantissa. In the context of musl this representation is produced from the range reduction process [2]. [1] https://en.wikipedia.org/wiki/Quadruple-precision_floating-p... [2] https://github.com/ifduyue/musl/blob/6d8a515796270eb6cec…

Does it make sense to use a double-double input when you only have double output? Sine is Lispchitz-limited by 1 so I don't see how this makes a meaningful difference.

Re: Implementing Cosine in C from Scratch (2020)

#46
post #40
post #24

>I couldn't find any notable projects on GitHub that use a table for trig functions, but I'm sure they exist. Doom?

Doom also uses the famous fast inverse square root method which although I know how it works still amazes me.

It doesn't, to the best of my knowledge. It appeared in an id game for the first time in Quake 3.

Re: Implementing Cosine in C from Scratch (2020)

#47
post #20

Mandatory Physics "troll" comment: For small angles, sin(x) ~= x and cos(x) ~= 1 -- the ["small angle approximation"]( https://en.wikipedia.org/wiki/Small-angle_approximation ) It's actually kind of ridiculous how many times it comes up and works well enough in undergraduate Mechanics.

This a perfectly nice Programming 101 example of a recursive function -- if an angle is too large, calculate its sine using the sine of the half-angle, otherwise return the angle (or, if you're fancy, some simple polynomial approximation of the sine). I'm sure everyone did this in school (we did, in fact).

It's not obvious when you should switch over to an approximation (base case), so I'd say it's not a good example to introduce recursion. I have never seen it, and I did not do it in school.

Re: Implementing Cosine in C from Scratch (2020)

#50
post #45

Earlier quoted context omitted.

It is a double-double representation [1], where a logical fp number is represented with a sum of two machine fp numbers x (head, larger) and y (tail, smaller). This effectively doubles the mantissa. In the context of musl this representation is produced from the range reduction process [2]. [1] https://en.wikipedia.org/wiki/Quadruple-precision_floating-p... [2] https://github.com/ifduyue/musl/blob/6d8a515796270eb6cec…

Does it make sense to use a double-double input when you only have double output? Sine is Lispchitz-limited by 1 so I don't see how this makes a meaningful difference.

The input might be double but the constant pi is not. Let f64(x) be a function from any real number to double, so that an ordinary expression `a + b` actually computes f64(a + b) and so on. Then in general f64(sin(x)) may differ from f64(sin(f64(x mod 2pi))); since you can't directly compute f64(sin(x mod 2pi)), you necessarily need more precision during argument reduction so that f64(sin(x)) = f64(sin(f64timeswhatever(x mod 2pi))).
Post reply on HN