diff --git a/loopy/prophormance.py b/loopy/prophormance.py
deleted file mode 100755
index 8b495a63a22921c3d92fb54065b4143aaac94c9c..0000000000000000000000000000000000000000
--- a/loopy/prophormance.py
+++ /dev/null
@@ -1,171 +0,0 @@
-from __future__ import division 
-from __future__ import absolute_import 
-import six 
-
-__copyright__ = "Copyright (C) 2015 James Stevens"
-
-__license__ = """
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-"""
-
-import numpy as np
-from islpy import dim_type
-import loopy as lp
-import pyopencl as cl
-import pyopencl.array
-from pymbolic.mapper.flop_counter import FlopCounter
-
-class ExpressionFlopCounter(FlopCounter):
-
-	def map_reduction(self, expr):
-		from warnings import warn
-		warn("ExpressionFlopCounter counting reduction expression as 0 flops.", stacklevel=2)
-		return 0
-
-# from pymbolic:
-
-	def map_tagged_variable(self, expr):
-		return 0
-
-	def map_variable(self, expr):
-		return 0
-
-	def map_wildcard(self, expr):
-		return 0
-
-	def map_function_symbol(self, expr):
-		return 0
-
-	def map_call(self, expr):
-		return 0
-
-	def map_call_with_kwargs(self, expr):
-		return 0
-
-	def map_subscript(self, expr):
-		return self.rec(expr.index)
-
-	def map_lookup(self, expr):
-		return 0
-
-	def map_sum(self, expr):
-		return 0
-
-	def map_product(self, expr):
-		return 0
-
-	def map_quotient(self, expr):
-		return 0
-
-	def map_floor_div(self, expr):
-		return 0
-
-	def map_remainder(self, expr):
-		return 0
-
-	def map_power(self, expr):
-		return 0
-
-	def map_left_shift(self, expr):
-		return 0
-
-	def map_right_shift(self, expr):
-		return 0
-
-	def map_bitwise_not(self, expr):
-		return 0
-
-	def map_bitwise_or(self, expr):
-		return 0
-
-	def map_bitwise_xor(self, expr):
-		return 0
-
-	def map_bitwise_and(self, expr):
-		return 0
-
-	def map_comparison(self, expr):
-		return 0
-
-	def map_logical_not(self, expr):
-		return 0
-
-	def map_logical_or(self, expr):
-		return 0
-
-	def map_logical_and(self, expr):
-		return 0
-
-	def map_if(self, expr):
-		return 0
-
-	def map_if_positive(self, expr):
-		return 0
-
-	def map_min(self, expr):
-		return 0
-
-	def map_max(self, expr):
-		return 0
-
-	def map_common_subexpression(self, expr):
-		return 0
-
-	def map_substitution(self, expr):
-		return 0
-
-	def map_derivative(self, expr):
-		return 0
-
-	def map_slice(self, expr):
-		return 0
-
-
-# to evaluate poly: poly.eval_with_dict(dictionary)
-def get_flop_poly(knl):
-	poly = 0
-	flopCounter = ExpressionFlopCounter()
-	for insn in knl.instructions:
-		# how many times is this instruction executed?
-		# check domain size:
-		insn_inames = knl.insn_inames(insn)
-		inames_domain = knl.get_inames_domain(knl.insn_inames(insn))
-		domain = (inames_domain.project_out_except(insn_inames, [dim_type.set]))
-		flops = flopCounter(insn.expression())
-		poly += flops*domain.card()
-	return poly
-
-
-'''
-class PerformanceForecaster:
-
-	# to evaluate poly: poly.eval_with_dict(dictionary)
-	def get_flop_poly(self, knl):
-		poly = 0
-		flopCounter = ExpressionFlopCounter()
-		for insn in knl.instructions:
-			# how many times is this instruction executed?
-			# check domain size:
-			insn_inames = knl.insn_inames(insn)
-			inames_domain = knl.get_inames_domain(knl.insn_inames(insn))
-			domain = (inames_domain.project_out_except(insn_inames, [dim_type.set]))
-			flops = flopCounter(insn.expression())
-			poly += flops*domain.card()
-		return poly
-'''
diff --git a/loopy/statistics.py b/loopy/statistics.py
new file mode 100755
index 0000000000000000000000000000000000000000..b45e62efd8750902802f205fa3b45a97fb1c7c55
--- /dev/null
+++ b/loopy/statistics.py
@@ -0,0 +1,151 @@
+from __future__ import division 
+from __future__ import absolute_import 
+import six 
+
+__copyright__ = "Copyright (C) 2015 James Stevens"
+
+__license__ = """
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+"""
+
+import numpy as np
+from islpy import dim_type
+import loopy as lp
+import pyopencl as cl
+import pyopencl.array
+from pymbolic.mapper.flop_counter import FlopCounter
+
+class ExpressionFlopCounter(FlopCounter):
+
+	# ExpressionFlopCounter extends FlopCounter extends CombineMapper extends RecursiveMapper
+	
+	def map_reduction(self, expr, knl):
+		inames_domain = knl.get_inames_domain(frozenset([expr.inames[0]]))
+		domain = (inames_domain.project_out_except(frozenset([expr.inames[0]]), [dim_type.set]))
+		if str(expr.operation) == 'sum' or str(expr.operation) == 'product' :
+			return domain.card()*(1+self.rec(expr.expr))
+		else:
+			from warnings import warn
+			warn("ExpressionFlopCounter counting reduction operation as 0 flops.", stacklevel=2)
+			return domain.card()*(0+self.rec(expr.expr))
+
+	# from pymbolic:
+
+	def map_tagged_variable(self, expr):
+		return 0
+
+	# def map_variable(self, expr):   # implemented in FlopCounter
+
+	def map_wildcard(self, expr):
+		return 0
+
+	def map_function_symbol(self, expr):
+		return 0
+
+	# def map_call(self, expr):  # implemented in CombineMapper, recurses
+	# def map_call_with_kwargs(self, expr):  # implemented in CombineMapper, recurses
+
+	def map_subscript(self, expr):  # implemented in CombineMapper
+		return self.rec(expr.index)
+
+	# def map_lookup(self, expr):  # implemented in CombineMapper, recurses
+	# def map_sum(self, expr)  # implemented in FlopCounter
+	# def map_product(self, expr):  # implemented in FlopCounter
+	# def map_quotient(self, expr):  # implemented in FlopCounter
+	# def map_floor_div(self, expr):  # implemented in FlopCounter
+
+	def map_remainder(self, expr):  # implemented in CombineMapper
+		return 0
+
+	# def map_power(self, expr):  # implemented in FlopCounter, recurses; coming soon
+
+	def map_left_shift(self, expr):  # implemented in CombineMapper, recurses; coming soon
+		return 0
+
+	def map_right_shift(self, expr):  # implemented in CombineMapper, maps to left_shift; coming soon
+		return 0
+
+	def map_bitwise_not(self, expr):  # implemented in CombineMapper, recurses; coming soon
+		return 0
+
+	def map_bitwise_or(self, expr):  # implemented in CombineMapper, maps to map_sum; coming soon
+		return 0
+
+	def map_bitwise_xor(self, expr):  # implemented in CombineMapper, maps to map_sum; coming soon
+		return 0
+
+	def map_bitwise_and(self, expr):  # implemented in CombineMapper, maps to map_sum; coming soon
+		return 0
+
+	def map_comparison(self, expr):  # implemented in CombineMapper, recurses; coming soon
+		return 0
+
+	def map_logical_not(self, expr):  # implemented in CombineMapper, maps to bitwise_not; coming soon
+		return 0
+
+	def map_logical_or(self, expr):  # implemented in CombineMapper, maps to map_sum; coming soon
+		return 0
+
+	def map_logical_and(self, expr):  # implemented in CombineMapper, maps to map_sum; coming soon
+		return 0
+
+	def map_if(self, expr):  # implemented in CombineMapper, recurses; coming soon
+		return 0
+
+	# def map_if_positive(self, expr):  # implemented in FlopCounter
+
+	def map_min(self, expr):  # implemented in CombineMapper, maps to map_sum; coming soon
+		return 0
+
+	def map_max(self, expr):  # implemented in CombineMapper, maps to map_sum 
+		return 0
+
+	def map_common_subexpression(self, expr):
+		print "TESTING-map_common_subexpression: ", expr
+		return 0
+
+	def map_substitution(self, expr):
+		print "TESTING-map_substitution: ", expr
+		return 0
+
+	def map_derivative(self, expr):
+		print "TESTING-map_derivative: ", expr
+		return 0
+
+	def map_slice(self, expr):
+		print "TESTING-map_slice: ", expr
+		return 0
+
+
+# to evaluate poly: poly.eval_with_dict(dictionary)
+def get_flop_poly(knl):
+	poly = 0
+	flopCounter = ExpressionFlopCounter()
+	for insn in knl.instructions:
+		# how many times is this instruction executed?
+		# check domain size:
+		insn_inames = knl.insn_inames(insn) 
+		inames_domain = knl.get_inames_domain(insn_inames)
+		domain = (inames_domain.project_out_except(insn_inames, [dim_type.set]))
+		#flops = flopCounter(insn.expression())
+		flops = flopCounter(insn.expression(),knl)
+		poly += flops*domain.card()
+	return poly
+
+
diff --git a/test/test_statistics.py b/test/test_statistics.py
new file mode 100644
index 0000000000000000000000000000000000000000..0df1865029ea145f52f225a3ef21036fb541f170
--- /dev/null
+++ b/test/test_statistics.py
@@ -0,0 +1,58 @@
+from __future__ import division
+
+__copyright__ = "Copyright (C) 2015 James Stevens"
+
+__license__ = """
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+"""
+
+import sys
+from pyopencl.tools import (
+        pytest_generate_tests_for_pyopencl
+        as pytest_generate_tests)
+from pymbolic.mapper.flop_counter import FlopCounter
+from loopy.statistics import *
+
+
+def test_flop_counter_basic(ctx_factory):
+
+	knl = lp.make_kernel(
+			"[n,m,l] -> {[i,k,j]: 0<=i<n and 0<=k<m and 0<=j<l}",
+			[
+			"""
+			c[i, j, k] = a[i,j,k]*b[i,j,k]/3.0+a[i,j,k]
+			e[i, k] = g[i,k]*h[i,k]
+			"""
+			],
+			name="weird", assumptions="n,m,l >= 1")
+
+	poly = get_flop_poly(knl)
+	n=512
+	m=256
+	l=128
+	flops = poly.eval_with_dict({'n':n, 'm':m, 'l':l})
+	assert flops == n*m+3*n*m*l
+
+
+if __name__ == "__main__":
+    if len(sys.argv) > 1:
+        exec(sys.argv[1])
+    else:
+        from py.test.cmdline import main
+        main([__file__])