The problem is essentially to count the number of bits in an integer. There's a good solution for this, which I'll show now.

This subroutine from MMIXware is supposed to do exactly this. This is for a 32-bit word though, not just 7 bits.

@ Here's a fun way to count the number of bits in a tetrabyte. [This classical trick is called the ``Gillies--Miller method for sideways addition'' in {\sl The Preparation of Programs for an Electronic Digital Computer\/} by Wilkes, Wheeler, and Gill, second edition (Reading, Mass.:\ Addison--Wesley, 1957), 191--193. Some of the tricks used here were suggested by Balbir Singh, Peter Rossmanith, and Stefan Schwoon.] @^Gillies, Donald Bruce@> @^Miller, Jeffrey Charles Percy@> @^Wilkes, Maurice Vincent@> @^Wheeler, David John@> @^Gill, Stanley@> @^Singh, Balbir@> @^Rossmanith, Peter@> @^Schwoon, Stefan@> @<Subr...@>= int count_bits @,@,@[ARGS((tetra))@];@+@t}\6{@> int count_bits(x) tetra x; { register int xx=x; xx=xx-((xx>>1)&0x55555555); xx=(xx&0x33333333)+((xx>>2)&0x33333333); xx=(xx+(xx>>4))&0x0f0f0f0f; xx=xx+(xx>>8); return (xx+(xx>>16)) & 0xff; }
Now if you understand how this works, you can probably convert it to efficent perl. I'm not sure I understand it in full, so the solution I'll write here may not be the same, thus may be slower.
#!perl use warnings; use strict; # the following subroutines couns the number of bits in an 8-bit integ +er sub sadd8_a { # my first solution -- without looking closely to your c +ode my($x) = @_; my $n = 0; for (my $k = 1; $k < 0x100; $k <<= 1) { 0 != ($x & $k) and $n++; } $n; } sub sadd8_b { # one of your solutions, modified a bit my ( $iDays ) = @_; my $iRes = 0; for ( 1, 2, 4, 8, 16, 32, 64, 128 ){ if ( $iDays & $_ ){ $iRes++; } } return $iRes; } sub sadd8_c { my($x) = @_; $x = ($x & 0b01010101) + ($x >> 1 & 0b01010101); $x = ($x & 0b00110011) + ($x >> 2 & 0b00110011); ($x & 0b00001111) + ($x >> 4); } # let's print an example for my $n (0 .. 31) { print sadd8_a($n), " "; } print "\n"; # test for my $n (0 .. 255) { my $a = sadd8_a($n); my $b = sadd8_b($n); my $c = sadd8_c($n); $a == $b && $b == $c or die "wrong results: $n $a $b $c"; } __END__

In reply to Re: Loops loosing Performance by ambrus
in thread Loops loosing Performance by PerlingTheUK

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.