If you have RAM to spare, (you are using perl, of course you do) you could build a 2048-entry lookup table, mask arg with 2047, shift once with the value from the table and then compare with 9007199254740993 once.
Something like: (untested)
static uint8_t ctz_table_11bit[2048] = { /* elided */ }; int uv_fits_double(UV arg) { arg >>= ctz_table_11bit[arg & 2047]; return arg < 9007199254740993; }
The relative elegance of this solution is probably a matter of opinion, but it should run much faster, since it is theoretically a single basic block and should be a candidate for inlining. This trades considerable computation for a single memory read, which will have relative performance depending on your hardware.
Here is some Perl code to generate that table: (I think this is the first time I have used formats; output spot checked for plausibility)
Update: change two magic numbers to use symbolic constant.#!/usr/bin/perl use strict; use warnings; use constant BITS => 11; our @pos; our @bits; our @val; format STDOUT_TOP= . $= = 1<<(BITS-1); format STDOUT = /* @### -> @0######### */ @#, /* @### -> @0######### */ @#, $pos[0], $bits[0], $val[0], $pos[1], $bits[1], $val[1], . print "static uint8_t ctz_table_",BITS,"bit[",1<<BITS,"] = {\n"; for (my $pos = 0; $pos < (1<<BITS); $pos += 2) { @pos = ($pos, $pos+1); @bits = map substr(unpack('B*', pack 'n', $_), -(BITS)), @pos; @val = map length((m/(0*?)\z/)[0]), @bits; write } print "};\n"; # EOF
In reply to Re: Detecting whether UV fits into an NV
by jcb
in thread Detecting whether UV fits into an NV
by syphilis
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |