         push:  -> @count++
         value: -> @count
         format: formatter
+        numInputs: 0
 
     countUnique: (formatter=usFmtInt) -> ([attr]) -> (data, rowKey, colKey) ->
         uniq: []
         push: (record) -> @uniq.push(record[attr]) if record[attr] not in @uniq
         value: -> @uniq.length
         format: formatter
+        numInputs: 1
 
     listUnique: (sep) -> ([attr]) -> (data, rowKey, colKey)  ->
         uniq: []
         push: (record) -> @uniq.push(record[attr]) if record[attr] not in @uniq
         value: -> @uniq.join sep
         format: (x) -> x
+        numInputs: 1
 
     sum: (formatter=usFmt) -> ([attr]) -> (data, rowKey, colKey) ->
         sum: 0
         push: (record) -> @sum += parseFloat(record[attr]) if not isNaN parseFloat(record[attr])
         value: -> @sum
         format: formatter
+        numInputs: 1
 
     average:  (formatter=usFmt) -> ([attr]) -> (data, rowKey, colKey) ->
         sum: 0

        push: (record) -> @inner.push record
        format: formatter
        value: -> @inner.value() / data.getAggregator(@selector...).inner.value()

#default aggregators & renderers use US naming and number formatting
aggregators = do (tpl = aggregatorTemplates) -> 

                Math.sqrt(0.410593603787454/ (@sumDenom*@sumDenom) + (@sumNum*(1 - @sumNum/ @sumDenom))/ (@sumDenom*@sumDenom)))/
                (1 + 1.642374415149816/@sumDenom)
        format: formatter
        numInputs: 2

    fractionOf: (wrapped, type="total", formatter=usFmtPct) -> (x...) -> (data, rowKey, colKey) ->
        selector: {total:[[],[]],row:[rowKey,[]],col:[[],colKey]}[type]
