001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2006-2011 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.olap.fun;
011
012import mondrian.calc.*;
013import mondrian.calc.impl.AbstractDoubleCalc;
014import mondrian.calc.impl.ValueCalc;
015import mondrian.mdx.ResolvedFunCall;
016import mondrian.olap.*;
017
018/**
019 * Definition of the <code>Covariance</code> and
020 * <code>CovarianceN</code> MDX functions.
021 *
022 * @author jhyde
023 * @since Mar 23, 2006
024 */
025class CovarianceFunDef extends FunDefBase {
026    static final ReflectiveMultiResolver CovarianceResolver =
027        new ReflectiveMultiResolver(
028            "Covariance",
029            "Covariance(<Set>, <Numeric Expression>[, <Numeric Expression>])",
030            "Returns the covariance of two series evaluated over a set (biased).",
031            new String[]{"fnxn", "fnxnn"},
032            CovarianceFunDef.class);
033
034    static final MultiResolver CovarianceNResolver =
035        new ReflectiveMultiResolver(
036            "CovarianceN",
037            "CovarianceN(<Set>, <Numeric Expression>[, <Numeric Expression>])",
038            "Returns the covariance of two series evaluated over a set (unbiased).",
039            new String[]{"fnxn", "fnxnn"},
040            CovarianceFunDef.class);
041
042    private final boolean biased;
043
044    public CovarianceFunDef(FunDef dummyFunDef) {
045        super(dummyFunDef);
046        this.biased = dummyFunDef.getName().equals("Covariance");
047    }
048
049    public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
050        final ListCalc listCalc =
051            compiler.compileList(call.getArg(0));
052        final Calc calc1 =
053            compiler.compileScalar(call.getArg(1), true);
054        final Calc calc2 =
055            call.getArgCount() > 2
056            ? compiler.compileScalar(call.getArg(2), true)
057            : new ValueCalc(call);
058        return new AbstractDoubleCalc(call, new Calc[] {listCalc, calc1, calc2})
059        {
060            public double evaluateDouble(Evaluator evaluator) {
061                TupleList memberList = listCalc.evaluateList(evaluator);
062                final int savepoint = evaluator.savepoint();
063                try {
064                    evaluator.setNonEmpty(false);
065                    final double covariance =
066                        (Double) covariance(
067                            evaluator,
068                            memberList,
069                            calc1,
070                            calc2,
071                            biased);
072                    return covariance;
073                } finally {
074                    evaluator.restore(savepoint);
075                }
076            }
077
078            public boolean dependsOn(Hierarchy hierarchy) {
079                return anyDependsButFirst(getCalcs(), hierarchy);
080            }
081        };
082    }
083}
084
085// End CovarianceFunDef.java