#include <stdio.h>
#include <math.h>
//gamma function using Lanczos approximation formula
//output result in log base e
//use exp() to convert back
//has a nice side effect: can store large values in small [power of e] form
double logGamma(double x)
{
double tmp
= (x
-0.5) * log(x
+4.5) - (x
+4.5); double ser = 1.0 + 76.18009173 / (x+0) - 86.50532033 / (x+1)
+ 24.01409822 / (x+2) - 1.231739516 / (x+3)
+ 0.00120858003 / (x+4) - 0.00000536382 / (x+5);
return tmp
+ log(ser
* sqrt(2*M_PI
) ); }
//result from logGamma() are actually (n-1)!
double combination(int n, int r)
{
return exp(logGamma
(n
+1)-( logGamma
(r
+1) + logGamma
(n
-r
+1) )); }
//primitive hamming weight counter
int hWeight(int x)
{
int count, y;
for (count=0, y=x; y; count++)
y &= y-1;
return count;
}
//-------------------------------------------------------------------------------------
//recursively find the previous group's "hamming weight member count" and sum them
int rCummGroupCount(int bitsize, int hw)
{
if (hw <= 0 || hw == bitsize)
return 1;
else
return round(combination(bitsize, hw)) + rCummGroupCount(bitsize,hw-1);
}
//-------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
int bitsize = 4, integer = 14;
int hw = hWeight(integer);
int groupStartIndex = rCummGroupCount(bitsize,hw-1);
printf("bitsize: %d\n", bitsize
); printf("integer: %d hamming weight: %d\n", integer
, hw
); printf("group start index: %d\n", groupStartIndex
); }
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxtYXRoLmg+CgovL2dhbW1hIGZ1bmN0aW9uIHVzaW5nIExhbmN6b3MgYXBwcm94aW1hdGlvbiBmb3JtdWxhCi8vb3V0cHV0IHJlc3VsdCBpbiBsb2cgYmFzZSBlCi8vdXNlIGV4cCgpIHRvIGNvbnZlcnQgYmFjawovL2hhcyBhIG5pY2Ugc2lkZSBlZmZlY3Q6IGNhbiBzdG9yZSBsYXJnZSB2YWx1ZXMgaW4gc21hbGwgW3Bvd2VyIG9mIGVdIGZvcm0KZG91YmxlIGxvZ0dhbW1hKGRvdWJsZSB4KQp7CiAgICBkb3VibGUgdG1wID0gKHgtMC41KSAqIGxvZyh4KzQuNSkgLSAoeCs0LjUpOwoJZG91YmxlIHNlciA9IDEuMCArIDc2LjE4MDA5MTczICAgICAvICh4KzApIC0gODYuNTA1MzIwMzMgICAgLyAoeCsxKQoJICAgICAgICAgICAgICAgICArIDI0LjAxNDA5ODIyICAgICAvICh4KzIpIC0gIDEuMjMxNzM5NTE2ICAgLyAoeCszKQoJICAgICAgICAgICAgICAgICArICAwLjAwMTIwODU4MDAzICAvICh4KzQpIC0gIDAuMDAwMDA1MzYzODIgLyAoeCs1KTsKCXJldHVybiB0bXAgKyBsb2coc2VyICogc3FydCgyKk1fUEkpICk7CQp9CgovL3Jlc3VsdCBmcm9tIGxvZ0dhbW1hKCkgYXJlIGFjdHVhbGx5IChuLTEpIQpkb3VibGUgY29tYmluYXRpb24oaW50IG4sIGludCByKQp7CglyZXR1cm4gZXhwKGxvZ0dhbW1hKG4rMSktKCBsb2dHYW1tYShyKzEpICsgbG9nR2FtbWEobi1yKzEpICkpOwp9CgovL3ByaW1pdGl2ZSBoYW1taW5nIHdlaWdodCBjb3VudGVyCmludCBoV2VpZ2h0KGludCB4KQp7CglpbnQgY291bnQsIHk7Cglmb3IgKGNvdW50PTAsIHk9eDsgeTsgY291bnQrKykKCQl5ICY9IHktMTsgCglyZXR1cm4gY291bnQ7Cn0KCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovL3JlY3Vyc2l2ZWx5IGZpbmQgdGhlIHByZXZpb3VzIGdyb3VwJ3MgImhhbW1pbmcgd2VpZ2h0IG1lbWJlciBjb3VudCIgYW5kIHN1bSB0aGVtCmludCByQ3VtbUdyb3VwQ291bnQoaW50IGJpdHNpemUsIGludCBodykKewoJaWYgKGh3IDw9IDAgfHwgaHcgPT0gYml0c2l6ZSkgCgkJcmV0dXJuIDE7CgllbHNlCgkJcmV0dXJuIHJvdW5kKGNvbWJpbmF0aW9uKGJpdHNpemUsIGh3KSkgKyByQ3VtbUdyb3VwQ291bnQoYml0c2l6ZSxody0xKTsKfQovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmludCBtYWluKGludCBhcmdjLCBjaGFyKiBhcmd2W10pCnsKCWludCBiaXRzaXplID0gNCwgaW50ZWdlciA9IDE0OwoJaW50IGh3ID0gaFdlaWdodChpbnRlZ2VyKTsKCWludCBncm91cFN0YXJ0SW5kZXggPSByQ3VtbUdyb3VwQ291bnQoYml0c2l6ZSxody0xKTsKCXByaW50ZigiYml0c2l6ZTogJWRcbiIsIGJpdHNpemUpOwoJcHJpbnRmKCJpbnRlZ2VyOiAlZCAgaGFtbWluZyB3ZWlnaHQ6ICVkXG4iLCBpbnRlZ2VyLCBodyk7CglwcmludGYoImdyb3VwIHN0YXJ0IGluZGV4OiAlZFxuIiwgZ3JvdXBTdGFydEluZGV4KTsKfQo=