package org.araqne.logdb.query.aggregator; import java.util.Arrays; import java.util.List; import org.araqne.logdb.Row; import org.araqne.logdb.query.aggregator.Covariance.CovarianceMapper; import org.araqne.logdb.query.aggregator.Covariance.CovarianceReducer; import org.araqne.logdb.query.aggregator.Variance.VarianceMapper; import org.araqne.logdb.query.aggregator.Variance.VarianceReducer; import org.araqne.logdb.query.command.NumberUtil; import org.araqne.logdb.query.expr.Expression; public class Slope extends AbstractAggregationFunction { Covariance covar; Variance var; public Slope(List<Expression> exprs) { super(exprs); covar = new Covariance(exprs); var = new Variance(Arrays.asList(exprs.get(0))); } @Override public String getName() { return "slope"; } @Override public void apply(Row map) { covar.apply(map); var.apply(map); } @Override public Object eval() { Number covarValue = (Number) covar.eval(); Number varValue = (Number) var.eval(); if (covarValue == null || varValue == null) return null; else return NumberUtil.div(covarValue, varValue); } @Override public void merge(AggregationFunction func) { Slope other = (Slope) func; this.covar.merge(other.covar); this.var.merge(other.var); } @Override public Object[] serialize() { Object[] result1 = this.covar.serialize(); Object[] result2 = this.var.serialize(); int resultLength = result1.length + result2.length; Object[] result = new Object[resultLength]; for (int i = 0; i < resultLength; i++) { if (i < result1.length) result[i] = result1[i]; else if (i < result1.length + result2.length) result[i] = result2[i - result1.length]; } return result; } @Override public void deserialize(Object[] values) { Object[] values1 = covar.serialize(); Object[] values2 = var.serialize(); for (int i = 0; i < values.length; i++) { if (i < values1.length) values1[i] = values[i]; else if (i < values1.length + values2.length) values2[i - values1.length] = values[i]; } covar.deserialize(values1); var.deserialize(values2); } @Override public void clean() { covar.clean(); var.clean(); } @Override public AggregationFunction clone() { Slope slope = new Slope(exprs); slope.covar = (Covariance) covar.clone(); slope.var = (Variance) var.clone(); return slope; } @Override public boolean canBeDistributed() { return true; } @Override public AggregationFunction mapper(List<Expression> exprs) { return new SlopeMapper(exprs); } @Override public AggregationFunction reducer(List<Expression> exprs) { return new SlopeReducer(exprs); } @Override public String toString() { return "slope(" + exprs.get(0) + ", " + exprs.get(1) + ")"; } public static class SlopeMapper extends AbstractAggregationFunction { CovarianceMapper covarMapper; VarianceMapper varMapper; public SlopeMapper(List<Expression> exprs) { super(exprs); covarMapper = new CovarianceMapper(exprs); varMapper = new VarianceMapper(Arrays.asList(exprs.get(0))); } @Override public String getName() { return "slopeMapper"; } @Override public void apply(Row map) { covarMapper.apply(map); varMapper.apply(map); } @Override public Object eval() { return this.serialize(); } @Override public void merge(AggregationFunction func) { SlopeMapper other = (SlopeMapper) func; this.covarMapper.merge(other.covarMapper); this.varMapper.merge(other.varMapper); } @Override public Object[] serialize() { Object[] result1 = this.covarMapper.serialize(); Object[] result2 = this.varMapper.serialize(); Object[] result = new Object[2]; result[0] = result1; result[1] = result2; return result; } @Override public void deserialize(Object[] values) { covarMapper.deserialize((Object[]) values[0]); varMapper.deserialize((Object[]) values[1]); } @Override public void clean() { covarMapper.clean(); varMapper.clean(); } @Override public AggregationFunction clone() { SlopeMapper slopeMapper = new SlopeMapper(exprs); slopeMapper.covarMapper = (CovarianceMapper) this.covarMapper.clone(); slopeMapper.varMapper = (VarianceMapper) this.varMapper.clone(); return slopeMapper; } @Override public String toString() { return "slopeMapper(" + exprs.get(0) + ", " + exprs.get(1) + ")"; } } public static class SlopeReducer extends AbstractAggregationFunction { CovarianceReducer covarReducer; VarianceReducer varReducer; public SlopeReducer(List<Expression> exprs) { super(exprs); covarReducer = new CovarianceReducer(exprs); varReducer = new VarianceReducer(exprs); } @Override public String getName() { return "slopeReducer"; } @Override public void apply(Row map) { Expression expr = exprs.get(0); Object obj = expr.eval(map); if (obj == null || !(obj instanceof Object[])) return; Object[] values = (Object[]) obj; Object[] values1 = (Object[]) values[0]; Object[] values2 = (Object[]) values[1]; AggregationFunction covarReducer = new CovarianceReducer(exprs); AggregationFunction varReducer = new VarianceReducer(exprs); covarReducer.deserialize(values1); varReducer.deserialize(values2); this.covarReducer.merge(covarReducer); this.varReducer.merge(varReducer); } @Override public Object eval() { Number covarValue = (Number) covarReducer.eval(); Number varValue = (Number) varReducer.eval(); if (covarValue == null || varValue == null) return null; else return NumberUtil.div(covarValue, varValue); } @Override public void merge(AggregationFunction func) { SlopeReducer other = (SlopeReducer) func; this.covarReducer.merge(other.covarReducer); this.varReducer.merge(other.varReducer); } @Override public Object[] serialize() { Object[] result1 = this.covarReducer.serialize(); Object[] result2 = this.varReducer.serialize(); Object[] result = new Object[2]; result[0] = result1; result[1] = result2; return result; } @Override public void deserialize(Object[] values) { covarReducer.deserialize((Object[]) values[0]); varReducer.deserialize((Object[]) values[1]); } @Override public void clean() { covarReducer.clean(); varReducer.clean(); } @Override public AggregationFunction clone() { SlopeReducer slopeReducer = new SlopeReducer(exprs); slopeReducer.covarReducer = (CovarianceReducer) this.covarReducer.clone(); slopeReducer.varReducer = (VarianceReducer) this.varReducer.clone(); return slopeReducer; } @Override public String toString() { return "slopeReducer(" + exprs.get(0) + ")"; } } }