My mental model of a CPU unfortunately tends toward x86.
> But of course, it might be possible to get that sqrt for free, too. Even if it takes 50 cycles, you might start one, do a few iterations without checking for ‘reached sqrt(n) yet’, and then start a loop testing for the limit.
On the CPU side, the branch predictor might make the sqrt free by pipelining it, but that starts to make the analysis a bit harder. Strange things can happen when you introduce branch prediction. The performance would also depend on ALU/FPU contention, hyperthreads, etc...
> If you really want to know for x_64, http://www.agner.org/optimize/ probably has the answers, but then, you would have to know the x86 instruction set, which is horrendous (compared to that 6502 or 68000). Even realising that there will be single, double and vector variants, the number of different instructions with ‘SQRT’ in their name I find in http://www.agner.org/optimize/instruction_tables.pdf is insane.
I've only just started reading Agner Fog's documentation (which is awesome), but it definitely seems like the place the find low level information of the ilk when it's needed. If you read through the instruction table though, you probably noticed there are fsqrt and (v)sqrt(p)(s/d). For most purposes, x87 is actually deprecated and SSE2, the latter, is preferred for scalar floating point. I would guess the Mill devs might have some insightful comments.
> And of course, probably, something completely out of left field could well be the fastest way to do this (by a few ns, probably). For example, modern CPUs can count leading zeros in an integer. If that instruction is fast (for x86, that is not a given; ‘bit scan reverse’ was slow on some CPUs) subtract from 64/32/16, and halve, and you have a decent approximation to 2log(sqrt(n)) (using ‘if n has b bits, sqrt(n) has about b/2’)
I'm not sure that's quite right. Counting leading zeros is normally very fast if you have the instruction, but those two functions diverge pretty quick. For a constant cost, my guess is that the accuracy lost wouldn't be performance gained. The other point is that accuracy is fairly important if you're testing for primality.