# Written by Behdad Esfahbod, 2008.
# Use as you wish.

def ref(a, c):
	# correct formula, using double.
	#
	return int (round (a * c / 255.))

	# integer equivalent of above.
	# it has 0 div, 1 mul, 1 add, 0 shift.
	#
	#return (a * c + 0x7f) / 255

	# this one perfectly matches current gdk code,
	# but I believe the above is correct.
	# they disagree in 128 cases in total.
	#
	#return (a * c + 0x7e) / 255

def old(a, c):
	# this is what gdkcairo.c currently does.
	# it has 0 div, 1 mul, 2 add, 2 shift.
	#
	t = a * c + 0x7f
	return ((t >> 8) + t) >> 8

def new(a, c):
	# this is my proposed method.
	#
	# (a * 0x10101) can be computed once for each pixel, so
	# it has 0 div, 1.33 mul, 1 add, 1 shift.
	#
	# also if the compiler sees fit (or if desired), the alpha mul
	# can be written as ((((a << 8) + a) << 8) + a), in which case
	# it has 0 div, 1 mul, 1.67 add, 1.67 shift.
	# 
	# and it all fits in uint32_t, so, all good.
	#
	return ((a * 0x10101) * c + 0x7fffff) >> 24

	# this one perfectly matches current gdk code,
	#return ((a * 0x10101) * c + 0x7effff) >> 24

# change these to compare different methods
f1 = ref
f2 = new

e = 0
for a in range (256):
	for c in range (256):
		ac1 = f1 (a, c)
		ac2 = f2 (a, c)
		if ac1 != ac2:
			print "alpha=%d color=%d f1=%d f2=%d delta=%+d" % \
				(a, c, ac1, ac2, ac2 - ac1)
			e += 1

print "%d cases didn't match" % e
