func newSpreadIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatSliceFuncReducer(FloatSpreadReduceSlice)
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, IntegerPointEmitter) {
			fn := NewIntegerSliceFuncReducer(IntegerSpreadReduceSlice)
			return fn, fn
		}
		return newIntegerReduceIntegerIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) {
			fn := NewUnsignedSliceFuncReducer(UnsignedSpreadReduceSlice)
			return fn, fn
		}
		return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported spread iterator type: %T", input)
	}
}
newSpreadIterator returns an iterator for operating on a spread() call.
package query
import (
	"fmt"
	"math"
	"sort"
	"time"
	"github.com/influxdata/influxql"
)
func NewCallIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	name := opt.Expr.(*influxql.Call).Name
	switch name {
	case "count":
		return newCountIterator(input, opt)
	case "min":
		return newMinIterator(input, opt)
	case "max":
		return newMaxIterator(input, opt)
	case "sum":
		return newSumIterator(input, opt)
	case "first":
		return newFirstIterator(input, opt)
	case "last":
		return newLastIterator(input, opt)
	case "mean":
		return newMeanIterator(input, opt)
	default:
		return nil, fmt.Errorf("unsupported function call: %s", name)
	}
}
func newCountIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, IntegerPointEmitter) {
			fn := NewFloatFuncIntegerReducer(FloatCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime})
			return fn, fn
		}
		return newFloatReduceIntegerIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, IntegerPointEmitter) {
			fn := NewIntegerFuncReducer(IntegerCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime})
			return fn, fn
		}
		return newIntegerReduceIntegerIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, IntegerPointEmitter) {
			fn := NewUnsignedFuncIntegerReducer(UnsignedCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime})
			return fn, fn
		}
		return newUnsignedReduceIntegerIterator(input, opt, createFn), nil
	case StringIterator:
		createFn := func() (StringPointAggregator, IntegerPointEmitter) {
			fn := NewStringFuncIntegerReducer(StringCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime})
			return fn, fn
		}
		return newStringReduceIntegerIterator(input, opt, createFn), nil
	case BooleanIterator:
		createFn := func() (BooleanPointAggregator, IntegerPointEmitter) {
			fn := NewBooleanFuncIntegerReducer(BooleanCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime})
			return fn, fn
		}
		return newBooleanReduceIntegerIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported count iterator type: %T", input)
	}
}
func FloatCountReduce(prev *IntegerPoint, curr *FloatPoint) (int64, int64, []interface{}) {
	if prev == nil {
		return ZeroTime, 1, nil
	}
	return ZeroTime, prev.Value + 1, nil
}
func IntegerCountReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) {
	if prev == nil {
		return ZeroTime, 1, nil
	}
	return ZeroTime, prev.Value + 1, nil
}
func UnsignedCountReduce(prev *IntegerPoint, curr *UnsignedPoint) (int64, int64, []interface{}) {
	if prev == nil {
		return ZeroTime, 1, nil
	}
	return ZeroTime, prev.Value + 1, nil
}
func StringCountReduce(prev *IntegerPoint, curr *StringPoint) (int64, int64, []interface{}) {
	if prev == nil {
		return ZeroTime, 1, nil
	}
	return ZeroTime, prev.Value + 1, nil
}
func BooleanCountReduce(prev *IntegerPoint, curr *BooleanPoint) (int64, int64, []interface{}) {
	if prev == nil {
		return ZeroTime, 1, nil
	}
	return ZeroTime, prev.Value + 1, nil
}
func newMinIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatFuncReducer(FloatMinReduce, nil)
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, IntegerPointEmitter) {
			fn := NewIntegerFuncReducer(IntegerMinReduce, nil)
			return fn, fn
		}
		return newIntegerReduceIntegerIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) {
			fn := NewUnsignedFuncReducer(UnsignedMinReduce, nil)
			return fn, fn
		}
		return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil
	case BooleanIterator:
		createFn := func() (BooleanPointAggregator, BooleanPointEmitter) {
			fn := NewBooleanFuncReducer(BooleanMinReduce, nil)
			return fn, fn
		}
		return newBooleanReduceBooleanIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported min iterator type: %T", input)
	}
}
func FloatMinReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) {
	if prev == nil || curr.Value < prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func IntegerMinReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) {
	if prev == nil || curr.Value < prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func UnsignedMinReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) {
	if prev == nil || curr.Value < prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func BooleanMinReduce(prev, curr *BooleanPoint) (int64, bool, []interface{}) {
	if prev == nil || (curr.Value != prev.Value && !curr.Value) || (curr.Value == prev.Value && curr.Time < prev.Time) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func newMaxIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatFuncReducer(FloatMaxReduce, nil)
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, IntegerPointEmitter) {
			fn := NewIntegerFuncReducer(IntegerMaxReduce, nil)
			return fn, fn
		}
		return newIntegerReduceIntegerIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) {
			fn := NewUnsignedFuncReducer(UnsignedMaxReduce, nil)
			return fn, fn
		}
		return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil
	case BooleanIterator:
		createFn := func() (BooleanPointAggregator, BooleanPointEmitter) {
			fn := NewBooleanFuncReducer(BooleanMaxReduce, nil)
			return fn, fn
		}
		return newBooleanReduceBooleanIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported max iterator type: %T", input)
	}
}
func FloatMaxReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) {
	if prev == nil || curr.Value > prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func IntegerMaxReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) {
	if prev == nil || curr.Value > prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func UnsignedMaxReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) {
	if prev == nil || curr.Value > prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func BooleanMaxReduce(prev, curr *BooleanPoint) (int64, bool, []interface{}) {
	if prev == nil || (curr.Value != prev.Value && curr.Value) || (curr.Value == prev.Value && curr.Time < prev.Time) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func newSumIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatFuncReducer(FloatSumReduce, &FloatPoint{Value: 0, Time: ZeroTime})
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, IntegerPointEmitter) {
			fn := NewIntegerFuncReducer(IntegerSumReduce, &IntegerPoint{Value: 0, Time: ZeroTime})
			return fn, fn
		}
		return newIntegerReduceIntegerIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) {
			fn := NewUnsignedFuncReducer(UnsignedSumReduce, &UnsignedPoint{Value: 0, Time: ZeroTime})
			return fn, fn
		}
		return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported sum iterator type: %T", input)
	}
}
func FloatSumReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) {
	if prev == nil {
		return ZeroTime, curr.Value, nil
	}
	return prev.Time, prev.Value + curr.Value, nil
}
func IntegerSumReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) {
	if prev == nil {
		return ZeroTime, curr.Value, nil
	}
	return prev.Time, prev.Value + curr.Value, nil
}
func UnsignedSumReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) {
	if prev == nil {
		return ZeroTime, curr.Value, nil
	}
	return prev.Time, prev.Value + curr.Value, nil
}
func newFirstIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatFuncReducer(FloatFirstReduce, nil)
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, IntegerPointEmitter) {
			fn := NewIntegerFuncReducer(IntegerFirstReduce, nil)
			return fn, fn
		}
		return newIntegerReduceIntegerIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) {
			fn := NewUnsignedFuncReducer(UnsignedFirstReduce, nil)
			return fn, fn
		}
		return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil
	case StringIterator:
		createFn := func() (StringPointAggregator, StringPointEmitter) {
			fn := NewStringFuncReducer(StringFirstReduce, nil)
			return fn, fn
		}
		return newStringReduceStringIterator(input, opt, createFn), nil
	case BooleanIterator:
		createFn := func() (BooleanPointAggregator, BooleanPointEmitter) {
			fn := NewBooleanFuncReducer(BooleanFirstReduce, nil)
			return fn, fn
		}
		return newBooleanReduceBooleanIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported first iterator type: %T", input)
	}
}
func FloatFirstReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) {
	if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func IntegerFirstReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) {
	if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func UnsignedFirstReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) {
	if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func StringFirstReduce(prev, curr *StringPoint) (int64, string, []interface{}) {
	if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func BooleanFirstReduce(prev, curr *BooleanPoint) (int64, bool, []interface{}) {
	if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && !curr.Value && prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func newLastIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatFuncReducer(FloatLastReduce, nil)
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, IntegerPointEmitter) {
			fn := NewIntegerFuncReducer(IntegerLastReduce, nil)
			return fn, fn
		}
		return newIntegerReduceIntegerIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) {
			fn := NewUnsignedFuncReducer(UnsignedLastReduce, nil)
			return fn, fn
		}
		return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil
	case StringIterator:
		createFn := func() (StringPointAggregator, StringPointEmitter) {
			fn := NewStringFuncReducer(StringLastReduce, nil)
			return fn, fn
		}
		return newStringReduceStringIterator(input, opt, createFn), nil
	case BooleanIterator:
		createFn := func() (BooleanPointAggregator, BooleanPointEmitter) {
			fn := NewBooleanFuncReducer(BooleanLastReduce, nil)
			return fn, fn
		}
		return newBooleanReduceBooleanIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported last iterator type: %T", input)
	}
}
func FloatLastReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) {
	if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func IntegerLastReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) {
	if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func UnsignedLastReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) {
	if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func StringLastReduce(prev, curr *StringPoint) (int64, string, []interface{}) {
	if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func BooleanLastReduce(prev, curr *BooleanPoint) (int64, bool, []interface{}) {
	if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value && !prev.Value) {
		return curr.Time, curr.Value, cloneAux(curr.Aux)
	}
	return prev.Time, prev.Value, prev.Aux
}
func NewDistinctIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatDistinctReducer()
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, IntegerPointEmitter) {
			fn := NewIntegerDistinctReducer()
			return fn, fn
		}
		return newIntegerReduceIntegerIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) {
			fn := NewUnsignedDistinctReducer()
			return fn, fn
		}
		return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil
	case StringIterator:
		createFn := func() (StringPointAggregator, StringPointEmitter) {
			fn := NewStringDistinctReducer()
			return fn, fn
		}
		return newStringReduceStringIterator(input, opt, createFn), nil
	case BooleanIterator:
		createFn := func() (BooleanPointAggregator, BooleanPointEmitter) {
			fn := NewBooleanDistinctReducer()
			return fn, fn
		}
		return newBooleanReduceBooleanIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported distinct iterator type: %T", input)
	}
}
func newMeanIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatMeanReducer()
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, FloatPointEmitter) {
			fn := NewIntegerMeanReducer()
			return fn, fn
		}
		return newIntegerReduceFloatIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, FloatPointEmitter) {
			fn := NewUnsignedMeanReducer()
			return fn, fn
		}
		return newUnsignedReduceFloatIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported mean iterator type: %T", input)
	}
}
func NewMedianIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	return newMedianIterator(input, opt)
}
func newMedianIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatSliceFuncReducer(FloatMedianReduceSlice)
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, FloatPointEmitter) {
			fn := NewIntegerSliceFuncFloatReducer(IntegerMedianReduceSlice)
			return fn, fn
		}
		return newIntegerReduceFloatIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, FloatPointEmitter) {
			fn := NewUnsignedSliceFuncFloatReducer(UnsignedMedianReduceSlice)
			return fn, fn
		}
		return newUnsignedReduceFloatIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported median iterator type: %T", input)
	}
}
func FloatMedianReduceSlice(a []FloatPoint) []FloatPoint {
	if len(a) == 1 {
		return a
	}
	sort.Sort(floatPointsByValue(a))
	if len(a)%2 == 0 {
		lo, hi := a[len(a)/2-1], a[(len(a)/2)]
		return []FloatPoint{{Time: ZeroTime, Value: lo.Value + (hi.Value-lo.Value)/2}}
	}
	return []FloatPoint{{Time: ZeroTime, Value: a[len(a)/2].Value}}
}
func IntegerMedianReduceSlice(a []IntegerPoint) []FloatPoint {
	if len(a) == 1 {
		return []FloatPoint{{Time: ZeroTime, Value: float64(a[0].Value)}}
	}
	sort.Sort(integerPointsByValue(a))
	if len(a)%2 == 0 {
		lo, hi := a[len(a)/2-1], a[(len(a)/2)]
		return []FloatPoint{{Time: ZeroTime, Value: float64(lo.Value) + float64(hi.Value-lo.Value)/2}}
	}
	return []FloatPoint{{Time: ZeroTime, Value: float64(a[len(a)/2].Value)}}
}
func UnsignedMedianReduceSlice(a []UnsignedPoint) []FloatPoint {
	if len(a) == 1 {
		return []FloatPoint{{Time: ZeroTime, Value: float64(a[0].Value)}}
	}
	sort.Sort(unsignedPointsByValue(a))
	if len(a)%2 == 0 {
		lo, hi := a[len(a)/2-1], a[(len(a)/2)]
		return []FloatPoint{{Time: ZeroTime, Value: float64(lo.Value) + float64(hi.Value-lo.Value)/2}}
	}
	return []FloatPoint{{Time: ZeroTime, Value: float64(a[len(a)/2].Value)}}
}
func NewModeIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatSliceFuncReducer(FloatModeReduceSlice)
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, IntegerPointEmitter) {
			fn := NewIntegerSliceFuncReducer(IntegerModeReduceSlice)
			return fn, fn
		}
		return newIntegerReduceIntegerIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) {
			fn := NewUnsignedSliceFuncReducer(UnsignedModeReduceSlice)
			return fn, fn
		}
		return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil
	case StringIterator:
		createFn := func() (StringPointAggregator, StringPointEmitter) {
			fn := NewStringSliceFuncReducer(StringModeReduceSlice)
			return fn, fn
		}
		return newStringReduceStringIterator(input, opt, createFn), nil
	case BooleanIterator:
		createFn := func() (BooleanPointAggregator, BooleanPointEmitter) {
			fn := NewBooleanSliceFuncReducer(BooleanModeReduceSlice)
			return fn, fn
		}
		return newBooleanReduceBooleanIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported median iterator type: %T", input)
	}
}
func FloatModeReduceSlice(a []FloatPoint) []FloatPoint {
	if len(a) == 1 {
		return a
	}
	sort.Sort(floatPointsByValue(a))
	mostFreq := 0
	currFreq := 0
	currMode := a[0].Value
	mostMode := a[0].Value
	mostTime := a[0].Time
	currTime := a[0].Time
	for _, p := range a {
		if p.Value != currMode {
			currFreq = 1
			currMode = p.Value
			currTime = p.Time
			continue
		}
		currFreq++
		if mostFreq > currFreq || (mostFreq == currFreq && currTime > mostTime) {
			continue
		}
		mostFreq = currFreq
		mostMode = p.Value
		mostTime = p.Time
	}
	return []FloatPoint{{Time: ZeroTime, Value: mostMode}}
}
func IntegerModeReduceSlice(a []IntegerPoint) []IntegerPoint {
	if len(a) == 1 {
		return a
	}
	sort.Sort(integerPointsByValue(a))
	mostFreq := 0
	currFreq := 0
	currMode := a[0].Value
	mostMode := a[0].Value
	mostTime := a[0].Time
	currTime := a[0].Time
	for _, p := range a {
		if p.Value != currMode {
			currFreq = 1
			currMode = p.Value
			currTime = p.Time
			continue
		}
		currFreq++
		if mostFreq > currFreq || (mostFreq == currFreq && currTime > mostTime) {
			continue
		}
		mostFreq = currFreq
		mostMode = p.Value
		mostTime = p.Time
	}
	return []IntegerPoint{{Time: ZeroTime, Value: mostMode}}
}
func UnsignedModeReduceSlice(a []UnsignedPoint) []UnsignedPoint {
	if len(a) == 1 {
		return a
	}
	sort.Sort(unsignedPointsByValue(a))
	mostFreq := 0
	currFreq := 0
	currMode := a[0].Value
	mostMode := a[0].Value
	mostTime := a[0].Time
	currTime := a[0].Time
	for _, p := range a {
		if p.Value != currMode {
			currFreq = 1
			currMode = p.Value
			currTime = p.Time
			continue
		}
		currFreq++
		if mostFreq > currFreq || (mostFreq == currFreq && currTime > mostTime) {
			continue
		}
		mostFreq = currFreq
		mostMode = p.Value
		mostTime = p.Time
	}
	return []UnsignedPoint{{Time: ZeroTime, Value: mostMode}}
}
func StringModeReduceSlice(a []StringPoint) []StringPoint {
	if len(a) == 1 {
		return a
	}
	sort.Sort(stringPointsByValue(a))
	mostFreq := 0
	currFreq := 0
	currMode := a[0].Value
	mostMode := a[0].Value
	mostTime := a[0].Time
	currTime := a[0].Time
	for _, p := range a {
		if p.Value != currMode {
			currFreq = 1
			currMode = p.Value
			currTime = p.Time
			continue
		}
		currFreq++
		if mostFreq > currFreq || (mostFreq == currFreq && currTime > mostTime) {
			continue
		}
		mostFreq = currFreq
		mostMode = p.Value
		mostTime = p.Time
	}
	return []StringPoint{{Time: ZeroTime, Value: mostMode}}
}
func BooleanModeReduceSlice(a []BooleanPoint) []BooleanPoint {
	if len(a) == 1 {
		return a
	}
	trueFreq := 0
	falsFreq := 0
	mostMode := false
	for _, p := range a {
		if p.Value {
			trueFreq++
		} else {
			falsFreq++
		}
	}
	if trueFreq >= falsFreq {
		mostMode = true
	}
	return []BooleanPoint{{Time: ZeroTime, Value: mostMode}}
}
func newStddevIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
	switch input := input.(type) {
	case FloatIterator:
		createFn := func() (FloatPointAggregator, FloatPointEmitter) {
			fn := NewFloatSliceFuncReducer(FloatStddevReduceSlice)
			return fn, fn
		}
		return newFloatReduceFloatIterator(input, opt, createFn), nil
	case IntegerIterator:
		createFn := func() (IntegerPointAggregator, FloatPointEmitter) {
			fn := NewIntegerSliceFuncFloatReducer(IntegerStddevReduceSlice)
			return fn, fn
		}
		return newIntegerReduceFloatIterator(input, opt, createFn), nil
	case UnsignedIterator:
		createFn := func() (UnsignedPointAggregator, FloatPointEmitter) {
			fn := NewUnsignedSliceFuncFloatReducer(UnsignedStddevReduceSlice)
			return fn, fn
		}
		return newUnsignedReduceFloatIterator(input, opt, createFn), nil
	default:
		return nil, fmt.Errorf("unsupported stddev iterator type: %T", input)
	}
}
func FloatStddevReduceSlice(a []FloatPoint) []FloatPoint {
	if len(a) < 2 {
		return []FloatPoint{{Time: ZeroTime, Nil: true}}
	}
	var mean float64
	var count int
	for _, p := range a {
		if math.IsNaN(p.Value) {
			continue
		}
		count++
		mean += (p.Value - mean) / float64(count)
	}
	var variance float64
	for _, p := range a {
		if math.IsNaN(p.Value) {
			continue
		}
		variance += math.Pow(p.Value-mean, 2)
	}
	return []FloatPoint{{
		Time:  ZeroTime,
		Value: math.Sqrt(variance / float64(count-1)),
	}}
}
func IntegerStddevReduceSlice(a []IntegerPoint) []FloatPoint {
	if len(a) < 2 {
		return []FloatPoint{{Time: ZeroTime, Nil: true}}
	}
	var mean float64
	var count int
	for _, p := range a {
		count++
		mean += (float64(p.Value) - mean) / float64(count)
	}
	var variance float64
	for _, p := range a {
		variance += math.Pow(float64(p.Value)-mean, 2)
	}
	return []FloatPoint{{
		Time:  ZeroTime,
		Value: math.Sqrt(variance / float64(count-1)),
	}}
}
func UnsignedStddevReduceSlice(a []UnsignedPoint) []FloatPoint {
	if len(a) < 2 {
		return []FloatPoint{{Time: ZeroTime, Nil: true}}
	}
	var mean float64
	var count int
	for _, p := range a {
		count++
		mean += (float64(p.Value) - mean) / float64(count)
	}
	var variance float64
	for _, p := range a {
		variance += math.Pow(float64(p.Value)-mean, 2)
	}
	return []FloatPoint{{
		Time:  ZeroTime,
		Value: math.Sqrt(variance / float64(count-1)),
	}}
}