    /* <CoffeeScript>
    {utils} = require('tztime')

    </CoffeeScript> */
    /**
     * @class Lumenize.functions
     *
     * Rules about dependencies:
     *
     *   * If a function can be calculated incrementally from an oldResult and newValues, then you do not need to specify dependencies
     *   * If a funciton can be calculated from other incrementally calculable results, then you need only specify those dependencies
     *   * If a function needs the full list of values to be calculated (like percentile coverage), then you must specify 'values'
     *   * To support the direct passing in of OLAP cube cells, you can provide a prefix (field name) so the key in dependentValues
     *     can be generated
     *   * 'count' is special and does not use a prefix because it is not dependent up a particular field
     *   * You should calculate the dependencies before you calculate the thing that is depedent. The OLAP cube does some
     *     checking to confirm you've done this.
     */
    /* <CoffeeScript>
    functions = {}

    functions._populateDependentValues = (values, dependencies, dependentValues = {}, prefix = '') ->
      out = {}
      for d in dependencies
        if d == 'count'
          if prefix == ''
            key = 'count'
          else
            key = '_count'
        else
          key = prefix + d
        unless dependentValues[key]?
          dependentValues[key] = functions[d](values, undefined, undefined, dependentValues, prefix)
        out[d] = dependentValues[key]
      return out

    </CoffeeScript> */
    /**
     * @method sum
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Number} The sum of the values
     */
    /* <CoffeeScript>
    functions.sum = (values, oldResult, newValues) ->
      if oldResult?
        temp = oldResult
        tempValues = newValues
      else
        temp = 0
        tempValues = values
      for v in tempValues
        temp += v
      return temp

    </CoffeeScript> */
    /**
     * @method product
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Number} The product of the values
     */
    /* <CoffeeScript>
    functions.product = (values, oldResult, newValues) ->
      if oldResult?
        temp = oldResult
        tempValues = newValues
      else
        temp = 1
        tempValues = values
      for v in tempValues
        temp = temp * v
      return temp

    </CoffeeScript> */
    /**
     * @method sumSquares
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Number} The sum of the squares of the values
     */
    /* <CoffeeScript>
    functions.sumSquares = (values, oldResult, newValues) ->
      if oldResult?
        temp = oldResult
        tempValues = newValues
      else
        temp = 0
        tempValues = values
      for v in tempValues
        temp += v * v
      return temp

    </CoffeeScript> */
    /**
     * @method sumCubes
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Number} The sum of the cubes of the values
     */
    /* <CoffeeScript>
    functions.sumCubes = (values, oldResult, newValues) ->
      if oldResult?
        temp = oldResult
        tempValues = newValues
      else
        temp = 0
        tempValues = values
      for v in tempValues
        temp += v * v * v
      return temp

    </CoffeeScript> */
    /**
     * @method lastValue
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or newValues
     * @param {Number} [oldResult] Not used. It is included to make the interface consistent.
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Number} The last value
     */
    /* <CoffeeScript>
    functions.lastValue = (values, oldResult, newValues) ->
      if newValues?
        return newValues[newValues.length - 1]
      return values[values.length - 1]

    </CoffeeScript> */
    /**
     * @method firstValue
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] Not used. It is included to make the interface consistent.
     * @return {Number} The first value
     */
    /* <CoffeeScript>
    functions.firstValue = (values, oldResult, newValues) ->
      if oldResult?
        return oldResult
      return values[0]

    </CoffeeScript> */
    /**
     * @method count
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Number} The length of the values Array
     */
    /* <CoffeeScript>
    functions.count = (values, oldResult, newValues) ->
      if oldResult?
        return oldResult + newValues.length
      return values.length

    </CoffeeScript> */
    /**
     * @method min
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Number} The minimum value or null if no values
     */
    /* <CoffeeScript>
    functions.min = (values, oldResult, newValues) ->
      if oldResult?
        return functions.min(newValues.concat([oldResult]))
      if values.length == 0
        return null
      temp = values[0]
      for v in values
        if v < temp
          temp = v
      return temp

    </CoffeeScript> */
    /**
     * @method max
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Number} The maximum value or null if no values
     */
    /* <CoffeeScript>
    functions.max = (values, oldResult, newValues) ->
      if oldResult?
        return functions.max(newValues.concat([oldResult]))
      if values.length == 0
        return null
      temp = values[0]
      for v in values
        if v > temp
          temp = v
      return temp

    </CoffeeScript> */
    /**
     * @method values
     * @member Lumenize.functions
     * @static
     * @param {Object[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Array} All values (allows duplicates). Can be used for drill down.
     */
    /* <CoffeeScript>
    functions.values = (values, oldResult, newValues) ->
      if oldResult?
        return oldResult.concat(newValues)
      return values
    #  temp = []
    #  for v in values
    #    temp.push(v)
    #  return temp

    </CoffeeScript> */
    /**
     * @method uniqueValues
     * @member Lumenize.functions
     * @static
     * @param {Object[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] for incremental calculation
     * @param {Number[]} [newValues] for incremental calculation
     * @return {Array} Unique values. This is good for generating an OLAP dimension or drill down.
     */
    /* <CoffeeScript>
    functions.uniqueValues = (values, oldResult, newValues) ->
      temp = {}
      if oldResult?
        for r in oldResult
          temp[r] = null
        tempValues = newValues
      else
        tempValues = values
      temp2 = []
      for v in tempValues
        temp[v] = null
      for key, value of temp
        temp2.push(key)
      return temp2

    </CoffeeScript> */
    /**
     * @method average
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] not used by this function but included so all functions have a consistent signature
     * @param {Number[]} [newValues] not used by this function but included so all functions have a consistent signature
     * @param {Object} [dependentValues] If the function can be calculated from the results of other functions, this allows
     *   you to provide those pre-calculated values.
     * @return {Number} The arithmetic mean
     */
    /* <CoffeeScript>
    functions.average = (values, oldResult, newValues, dependentValues, prefix) ->
      {count, sum} = functions._populateDependentValues(values, functions.average.dependencies, dependentValues, prefix)
      if count is 0
        return null
      else
        return sum / count

    functions.average.dependencies = ['count', 'sum']

    </CoffeeScript> */
    /**
     * @method errorSquared
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] not used by this function but included so all functions have a consistent signature
     * @param {Number[]} [newValues] not used by this function but included so all functions have a consistent signature
     * @param {Object} [dependentValues] If the function can be calculated from the results of other functions, this allows
     *   you to provide those pre-calculated values.
     * @return {Number} The error squared
     */
    /* <CoffeeScript>
    functions.errorSquared = (values, oldResult, newValues, dependentValues, prefix) ->
      {count, sum} = functions._populateDependentValues(values, functions.errorSquared.dependencies, dependentValues, prefix)
      mean = sum / count
      errorSquared = 0
      for v in values
        difference = v - mean
        errorSquared += difference * difference
      return errorSquared

    functions.errorSquared.dependencies = ['count', 'sum']

    </CoffeeScript> */
    /**
     * @method variance
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] not used by this function but included so all functions have a consistent signature
     * @param {Number[]} [newValues] not used by this function but included so all functions have a consistent signature
     * @param {Object} [dependentValues] If the function can be calculated from the results of other functions, this allows
     *   you to provide those pre-calculated values.
     * @return {Number} The variance
     */
    /* <CoffeeScript>
    functions.variance = (values, oldResult, newValues, dependentValues, prefix) ->
      {count, sum, sumSquares} = functions._populateDependentValues(values, functions.variance.dependencies, dependentValues, prefix)
      if count is 0
        return null
      else if count is 1
        return 0
      else
        return (count * sumSquares - sum * sum) / (count * (count - 1))

    functions.variance.dependencies = ['count', 'sum', 'sumSquares']

    </CoffeeScript> */
    /**
     * @method standardDeviation
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] not used by this function but included so all functions have a consistent signature
     * @param {Number[]} [newValues] not used by this function but included so all functions have a consistent signature
     * @param {Object} [dependentValues] If the function can be calculated from the results of other functions, this allows
     *   you to provide those pre-calculated values.
     * @return {Number} The standard deviation
     */
    /* <CoffeeScript>
    functions.standardDeviation = (values, oldResult, newValues, dependentValues, prefix) ->
      return Math.sqrt(functions.variance(values, oldResult, newValues, dependentValues, prefix))

    functions.standardDeviation.dependencies = functions.variance.dependencies

    </CoffeeScript> */
    /**
     * @method percentileCreator
     * @member Lumenize.functions
     * @static
     * @param {Number} p The percentile for the resulting function (50 = median, 75, 99, etc.)
     * @return {Function} A function to calculate the percentile
     *
     * When the user passes in `p<n>` as an aggregation function, this `percentileCreator` is called to return the appropriate
     * percentile function. The returned function will find the `<n>`th percentile where `<n>` is some number in the form of
     * `##[.##]`. (e.g. `p40`, `p99`, `p99.9`).
     *
     * There is no official definition of percentile. The most popular choices differ in the interpolation algorithm that they
     * use. The function returned by this `percentileCreator` uses the Excel interpolation algorithm which differs from the NIST
     * primary method. However, NIST lists something very similar to the Excel approach as an acceptible alternative. The only
     * difference seems to be for the edge case for when you have only two data points in your data set. Agreement with Excel,
     * NIST's acceptance of it as an alternative (almost), and the fact that it makes the most sense to me is why this approach
     * was chosen.
     *
     * http://en.wikipedia.org/wiki/Percentile#Alternative_methods
     *
     * Note: `median` is an alias for p50. The approach chosen for calculating p50 gives you the
     * exact same result as the definition for median even for edge cases like sets with only one or two data points.
     *
     */
    /* <CoffeeScript>
    functions.percentileCreator = (p) ->
      f = (values, oldResult, newValues, dependentValues, prefix) ->
        unless values?
          {values} = functions._populateDependentValues(values, ['values'], dependentValues, prefix)
        if values.length is 0
          return null
        sortfunc = (a, b) ->
          return a - b
        vLength = values.length
        values.sort(sortfunc)
        n = (p * (vLength - 1) / 100) + 1
        k = Math.floor(n)
        d = n - k
        if n == 1
          return values[1 - 1]
        if n == vLength
          return values[vLength - 1]
        return values[k - 1] + d * (values[k] - values[k - 1])
      f.dependencies = ['values']
      return f

    </CoffeeScript> */
    /**
     * @method median
     * @member Lumenize.functions
     * @static
     * @param {Number[]} [values] Must either provide values or oldResult and newValues
     * @param {Number} [oldResult] not used by this function but included so all functions have a consistent signature
     * @param {Number[]} [newValues] not used by this function but included so all functions have a consistent signature
     * @param {Object} [dependentValues] If the function can be calculated from the results of other functions, this allows
     *   you to provide those pre-calculated values.
     * @return {Number} The median
     */
    /* <CoffeeScript>
    functions.median = functions.percentileCreator(50)

    functions.expandFandAs = (a) ->
    </CoffeeScript> */
      /**
       * @method expandFandAs
       * @member Lumenize.functions
       * @static
       * @param {Object} a Will look like this `{as: 'mySum', f: 'sum', field: 'Points'}`
       * @return {Object} returns the expanded specification
       *
       * Takes specifications for functions and expands them to include the actual function and 'as'. If you do not provide
       * an 'as' property, it will build it from the field name and function with an underscore between. Also, if the
       * 'f' provided is a string, it is copied over to the 'metric' property before the 'f' property is replaced with the
       * actual function. `{field: 'a', f: 'sum'}` would expand to `{as: 'a_sum', field: 'a', metric: 'sum', f: [Function]}`.
       */
    /* <CoffeeScript>
      utils.assert(a.f?, "'f' missing from specification: \n#{JSON.stringify(a, undefined, 4)}")
      if utils.type(a.f) == 'function'
        utils.assert(a.as?, 'Must provide "as" field with your aggregation when providing a user defined function')
        a.metric = a.f.toString()
      else if functions[a.f]?
        a.metric = a.f
        a.f = functions[a.f]
      else if a.f.substr(0, 1) == 'p'
        a.metric = a.f
        p = /\p(\d+(.\d+)?)/.exec(a.f)[1]
        a.f = functions.percentileCreator(Number(p))
      else
        throw new Error("#{a.f} is not a recognized built-in function")

      unless a.as?
        if a.metric == 'count'
          a.field = ''
          a.metric = 'count'
        a.as = "#{a.field}_#{a.metric}"
        utils.assert(a.field? or a.f == 'count', "'field' missing from specification: \n#{JSON.stringify(a, undefined, 4)}")
      return a

    functions.expandMetrics = (metrics = [], addCountIfMissing = false, addValuesForCustomFunctions = false) ->
    </CoffeeScript> */
      /**
       * @method expandMetrics
       * @member Lumenize.functions
       * @static
       * @private
       *
       * This is called internally by several Lumenize Calculators. You should probably not call it.
       */
    /* <CoffeeScript>
      confirmMetricAbove = (m, fieldName, aboveThisIndex) ->
        if m is 'count'
          lookingFor = '_' + m
        else
          lookingFor = fieldName + '_' + m
        i = 0
        while i < aboveThisIndex
          currentRow = metrics[i]
          if currentRow.as == lookingFor
            return true
          i++
        # OK, it's not above, let's now see if it's below. Then throw error.
        i = aboveThisIndex + 1
        metricsLength = metrics.length
        while i < metricsLength
          currentRow = metrics[i]
          if currentRow.as == lookingFor
            throw new Error("Depdencies must appear before the metric they are dependant upon. #{m} appears after.")
          i++
        return false

      assureDependenciesAbove = (dependencies, fieldName, aboveThisIndex) ->
        for d in dependencies
          unless confirmMetricAbove(d, fieldName, aboveThisIndex)
            if d == 'count'
              newRow = {f: 'count'}
            else
              newRow = {f: d, field: fieldName}
            functions.expandFandAs(newRow)
            metrics.unshift(newRow)
            return false
        return true

      # add values for custom functions
      if addValuesForCustomFunctions
        for m, index in metrics
          if utils.type(m.f) is 'function'
            unless m.f.dependencies?
              m.f.dependencies = []
            unless m.f.dependencies[0] is 'values'
              m.f.dependencies.push('values')
            unless confirmMetricAbove('values', m.field, index)
              valuesRow = {f: 'values', field: m.field}
              functions.expandFandAs(valuesRow)
              metrics.unshift(valuesRow)

      hasCount = false
      for m in metrics
        functions.expandFandAs(m)
        if m.metric is 'count'
          hasCount = true

      if addCountIfMissing and not hasCount
        countRow = {f: 'count'}
        functions.expandFandAs(countRow)
        metrics.unshift(countRow)

      index = 0
      while index < metrics.length  # intentionally not caching length because the loop can add rows
        metricsRow = metrics[index]
        if utils.type(metricsRow.f) is 'function'
          dependencies = ['values']
        if metricsRow.f.dependencies?
          unless assureDependenciesAbove(metricsRow.f.dependencies, metricsRow.field, index)
            index = -1
        index++

      return metrics

    exports.functions = functions
    </CoffeeScript> */