#!/usr/bin/env python """ combino.py -- combinatory stuff related to squozen_code.html and combos.html . The table() function creates a table used on combos.html . """ from factorial import * from math import log, floor def right0( s ): """ Estimate of "linear" part of nbitsC(s) function based on combinations nbitsC(s) = log( (1000000+2**32-1)/1000000, 2 ) # 12.0687673 + log( (999999 +2**32-1 )! * (2**32-1-s)! / ((999999 +2**32-1-s)! * (2**32-1 )!), 2 ) and Stirling's formula. Using Stirlings formula adds wrinkles that aren't really there. """ y = log2_factorial(999999+2**32-1) + log2_factorial(2**32-1-s) y -= log2_factorial(999999+2**32-1-s) + log2_factorial(2**32-1) return y def right1(s): """ estimate of "linear" part of nbits(s) function based on combinations nbitsC(s) = log( (1000000+2**32-1)/1000000, 2 ) # 12.0687673 + log( (999999 +2**32-1 )! * (2**32-1-s)! / ((999999 +2**32-1-s)! * (2**32-1 )!), 2 ) Exact but slow. Doesn't like s to be a float. """ result = 0 for i in xrange(1,s+1): result += log( (999999.0+2**32-i) / (2**32-i), 2 ) return result def right2( s, npieces=10000 ): """ Estimate "linear" part of nbits(s) function based on combinations. estimate of "linear" part of nbits(s) function based on combinations nbitsC(s) = log( (1000000+2**32-1)/1000000, 2 ) # 12.0687673 + log( (999999 +2**32-1 )! * (2**32-1-s)! / ((999999 +2**32-1-s)! * (2**32-1 )!), 2 ) Medium-accurate. Medium-fast. Doesn't like s to be a float. npieces is ballpark how many pieces to break the sum into. """ result = 0 # i will range from 2**32-1 down to 2**32-s # Because i is the denominator, average over smaller and smaller # groups of terms as i gets smaller. i = 2**32 - 1 bottom = 2**32 - s while i > bottom + npieces: j = max( bottom + npieces, int( i - i / npieces - 1 ) ) n = i - j + 1 j = ( i + j ) * .5 result += log( (999999.0 + j) / j, 2 ) * n i -= n while i >= bottom: result += log( (999999.0 + i) / i, 2 ) i -= 1 return result def r2t(): """ This compares the result of right2() to that of right1() for accuracy. """ for i in [ 1, 2, 10, 100, 200, 500, 1000, 4000, 9000, 100000, 1000000 ]: r2 = right2(i)/i if i <= 1000000: r1 = right1(i)/i r1s = "%16.14f" % r1 d = (r2-r1)/r1 else: r1s = "%16s" % " " d = "" print "%10d" % i, r1s, "%16.14f" % r2, d def table(): print """ """ print '
| ' + heading + ' | '
print ' |||
' + istr + astr + ' | '
# nbitsC(s)
print ' '+b1, "%12.3f " % (nbitsCs),
print b0+' | '
# ( nbitsC(s)-nbitsC(0) ) / s
print ' ', "%16.14f" % ( r2 / i ), ' | ',
# nbitsC( 2*32-1 ) - nbitsC( s )
print ' ', "%12.3f " % ( nbitsC232_1 - nbitsCs ),
print ' | '
print '