Hacker News new | ask | show | jobs
by imalex 1828 days ago
Wow, that is indeed way cooler than what I knew! Thanks a lot for sharing (I wrote the blog post).

As for square roots, the reason why you can't use the underlying architecture is that it only works on the native i16 type. That's why I had to reimplement integer square root in the Int32 and then fixed point square root using that.

If you're saying that I could just ignore the Int32 part of the code and implement square roots just for the fixed point using the underlying architecture, that's definitely doable, but I'd be concerned about Newton's method (specifically the squaring of x_n) overflowing the fixed point. Maybe it'd work and I haven't thought it through enough. Thanks for the suggestion :D

1 comments

> As for square roots, the reason why you can't use the underlying architecture is that it only works on the native i16 type.

My understanding of your code is that you've got `struct Number { int16 a,b,c,d; };` and the value of a number is equal to the floating point number 256.0a + b + c / 256.0 + d / 65536.0. (if the arch had floats, which it doesn't) If this assumption is wrong, my bad.

What I'm proposing is that you do `b = i16.sqrt(256a + b); a = 0;` then do 1-2 iterations of newton's method. For instance, if you have the value 1234.56789 then i16.sqrt(256*a+b) = i16.sqrt(1234) = 35. So your first approximation is x = 35.56789. Do x = (x + 1234.56789/x)/2, and with floats you get x = 35.139035. Do it again, you get x = 35.136418. The true value is also 35.136418, so there ya go.

> I'd be concerned about Newton's method (specifically the squaring of x_n) overflowing the fixed point.

I may have lost the plot. Are you calculating _inverse_ square root? x_n isn't squared for Newton's method of square root, but it is for inverse square root.

(Either way, the square of the square root of a number should be the same as the original number. So if you have overflow, you have other problems.)

Unrelated: What do you need pi and trig functions for? I wrote a ray tracer (actually a path tracer, same diff) about a year ago, and I only used trig/pi to set up the camera for the render. While the render was actually rendering, no trig was happening. It didn't matter for me, so I just used the standard library, but in your case it would probably be fine to use slow brutish methods.

OK, I got what you're saying now, thanks! I got my wires crossed; I thought Newton's method was something else, but I was actually already implementing that.

I think it's a clever idea to use the native square root to seed the guess. That hadn't occurred to me. In my solution, I do integer square roots, and the fixed just dispatches to that, so I could drastically improve my guess if I used the native square root there. Nice idea!

I use pi just for normalization of the light power: https://github.com/aquach/from-nand-to-raytracer/blob/main/r...

And I don't use trig. I mention it just for fun. In the original Rust raytracer tutorial, they use trig to set up the field of view, but I hardcoded it to 90 degrees to remove the trig.