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) 2010-2013 Pentaho and others
008// All Rights Reserved.
009*/
010package mondrian.rolap.agg;
011
012
013import mondrian.olap.Util;
014import mondrian.rolap.CellKey;
015import mondrian.rolap.SqlStatement;
016import mondrian.spi.SegmentBody;
017import mondrian.util.Pair;
018
019import java.util.*;
020
021/**
022 * Implementation of {@link mondrian.rolap.agg.DenseSegmentDataset} that stores
023 * values of type {@code double}.
024 *
025 * @author jhyde
026 */
027class DenseDoubleSegmentDataset extends DenseNativeSegmentDataset {
028    final double[] values; // length == m[0] * ... * m[axes.length-1]
029
030    /**
031     * Creates a DenseDoubleSegmentDataset.
032     *
033     * @param axes Segment axes, containing actual column values
034     * @param size Number of coordinates
035     */
036    DenseDoubleSegmentDataset(SegmentAxis[] axes, int size) {
037        this(axes, new double[size], Util.bitSetBetween(0, size));
038    }
039
040    /**
041     * Creates a populated DenseDoubleSegmentDataset.
042     *
043     * @param axes Segment axes, containing actual column values
044     * @param values Cell values; not copied
045     * @param nullIndicators Null indicators
046     */
047    DenseDoubleSegmentDataset(
048        SegmentAxis[] axes, double[] values, BitSet nullIndicators)
049    {
050        super(axes, nullIndicators);
051        this.values = values;
052    }
053
054    public double getDouble(CellKey key) {
055        int offset = key.getOffset(axisMultipliers);
056        return values[offset];
057    }
058
059    public Object getObject(CellKey pos) {
060        if (values.length == 0) {
061            // No values means they are all null.
062            // We can't call isNull because we risk going into a SOE. Besides,
063            // this is a tight loop and we can skip over one VFC.
064            return null;
065        }
066        int offset = pos.getOffset(axisMultipliers);
067        return getObject(offset);
068    }
069
070    public Double getObject(int offset) {
071        final double value = values[offset];
072        if (value == 0 && isNull(offset)) {
073            return null;
074        }
075        return value;
076    }
077
078    public boolean exists(CellKey pos) {
079        return true;
080    }
081
082    public void populateFrom(int[] pos, SegmentDataset data, CellKey key) {
083        final int offset = getOffset(pos);
084        final double value = values[offset] = data.getDouble(key);
085        if (value != 0d || !data.isNull(key)) {
086            nullValues.clear(offset);
087        }
088    }
089
090    public void populateFrom(
091        int[] pos, SegmentLoader.RowList rowList, int column)
092    {
093        final int offset = getOffset(pos);
094        final double value = values[offset] = rowList.getDouble(column);
095        if (value != 0d || !rowList.isNull(column)) {
096            nullValues.clear(offset);
097        }
098    }
099
100    public SqlStatement.Type getType() {
101        return SqlStatement.Type.DOUBLE;
102    }
103
104    void set(int k, double d) {
105        values[k] = d;
106    }
107
108    protected int getSize() {
109        return values.length;
110    }
111
112    public SegmentBody createSegmentBody(
113        List<Pair<SortedSet<Comparable>, Boolean>> axes)
114    {
115        return new DenseDoubleSegmentBody(
116            nullValues,
117            values,
118            axes);
119    }
120}
121
122// End DenseDoubleSegmentDataset.java