It's useful when you want to "average" things that have different units, so addition is undefined.

Classic example is if you want to average the runtimes of different benchmarks to get a measure of performance (e.g. of CPUs), scaled relative to some reference to give a dimensionless number. If you use an ordinary mean, the choice of reference can change which is fastest, while the geometric mean gives the same relative ordering regardless of which reference is chosen.

Annoyingly, I wanted to dig up what hypotactually did, eg if it's a CPU operation implementing IEE754 directly, like some methods are, but it just calls into libc, which for me pretty much immediately just hits the wall of vcruntime. Gross.

Another way to do this would be to subtract k from both exponents to bring the larger one close to 0, then compute sqrt(a*a + b*b), and finally add k to the exponent of the result.

The most expensive part is computing sqrt, which the naive algorithm doesn't avoid, so this doesn't seem like a worthwhile optimization given that it sacrifices half of the range of the exponent.

Well I mean more that this is a function for increased correctness, it's not a "go fast" button you should go use in your vec because "it's written by smart people"

I would assume the expensive part would actually be branch misprediction in the cleanup (assuming the compiler can't do some magic), and the sqrt can both be skipped in many cases (comparing the square of the hypotenuse) and the has CPU native implementations that seem quite performant - depending on your precision needs.

It's not clear to me that the halved exponent matters in most cases? Graphics generally cares more about precision than range, and logic doesn't really care about either. You have to be doing something pretty odd to need more than 10¹⁹ units of distance with precision of 1/10⁶ units. But at least something to keep in mind if you're doing an open world.

"better" only makes sense in the context of a purpose: I doubt you'd notice a difference in the vast majority of cases for performance. If you see this pop up in a profile, give the dumb version a try, sure, but really you should be looking at dedicated vector math libraries that have already micro-optimized SIMD code.

Otherwise it's mostly stylistic preference and awareness of what the technical differences are, in my opinion.

How would a librarie optimize code like this than? I can't imagine how that would work when it's a short formula? (I don't know what's possible.) Or do you mean in general for other functions you could use as well?

I need to continuously calculate the hypotenuse, and possibly other stuff for a lot of objects every few ms. So I might need libraries like that. Or at least, be nice to look at what they have to offer.

Maybe I should look into SIMD code, since I don't know what that is.

SIMD stands for "Single-Instruction Multiple Dispatch," and is the generic term for CPU instructions that let you do the same operation on several different memory locations at the same time. This is more efficient in terms of silicon/microcode because the instruction decoding only has to happen once.

As math-heavy code tends to perform the same calculations on lots of data points, this can provide a significant speedup in common cases.

You don't necessarily need to write explicit SIMD code for simple cases. The optimizer is capable of recognizing that repeated arithmetic (such as adding the four components of two vectors to each other) can be processed using SIMD instructions.

Consult the generated assembly for straightforward code before complicating it.