in reply to Detecting whether UV fits into an NV
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
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^2: Detecting whether UV fits into an NV
by syphilis (Archbishop) on Mar 02, 2020 at 08:07 UTC | |
by jcb (Parson) on Mar 03, 2020 at 00:31 UTC | |
by syphilis (Archbishop) on Mar 04, 2020 at 04:07 UTC |
In Section
Seekers of Perl Wisdom