/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.server.types.mcompat.aggr; import com.foundationdb.server.error.AkibanInternalException; import com.foundationdb.server.types.TAggregator; import com.foundationdb.server.types.TFixedTypeAggregator; import com.foundationdb.server.types.TInstance; import com.foundationdb.server.types.mcompat.mtypes.MApproximateNumber; import com.foundationdb.server.types.value.Value; import com.foundationdb.server.types.value.ValueSource; import com.foundationdb.server.types.value.ValueTarget; public class MStdDevVarAggregate extends TFixedTypeAggregator { enum Func { // These are the actual aggregate functions. They are only // here so that we can distinguish from regular functions // early enough for the optimizer to transform them. VAR_POP, VAR_SAMP, STDDEV_POP, STDDEV_SAMP, // These are the partial aggregators. SUM, SUM_SQUARE } public static final TAggregator[] INSTANCES = { new MStdDevVarAggregate(Func.VAR_POP, "VAR_POP"), new MStdDevVarAggregate(Func.VAR_SAMP, "VAR_SAMP"), new MStdDevVarAggregate(Func.STDDEV_POP, "STDDEV_POP"), new MStdDevVarAggregate(Func.STDDEV_SAMP, "STDDEV_SAMP"), new MStdDevVarAggregate(Func.SUM, "_VAR_SUM"), new MStdDevVarAggregate(Func.SUM_SQUARE, "_VAR_SUM_2") }; private final Func func; private MStdDevVarAggregate(Func func, String name) { super(name, MApproximateNumber.DOUBLE); this.func = func; } @Override public void input(TInstance type, ValueSource source, TInstance stateType, Value state, Object del) { if (source.isNull()) return; double x = source.getDouble(); double sum = state.hasAnyValue() ? state.getDouble() : 0; switch (func) { case SUM: sum += x; break; case SUM_SQUARE: sum += x * x; break; default: throw new AkibanInternalException("Aggregator for " + displayName() + " should have been optimized out"); } state.putDouble(sum); } @Override public void emptyValue(ValueTarget state) { state.putNull(); } }