/** * diqube: Distributed Query Base. * * Copyright (C) 2015 Bastian Gloeckle * * This file is part of diqube. * * diqube 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 org.diqube.data.types.lng.compression; import org.diqube.data.types.lng.array.BitEfficientLongArray; import org.diqube.data.types.lng.array.RunLengthLongArray; import org.diqube.data.types.lng.array.TransitiveExplorableCompressedLongArray.TransitiveCompressionRatioCalculator; import org.testng.Assert; import org.testng.annotations.Test; /** * Tests compression ratios calculated by a combination of {@link RunLengthLongArray} with a * {@link BitEfficientLongArray}. * * @author Bastian Gloeckle */ public class RunLengthWithBitEfficientRatioTest { @Test public void withMinValueZeroTest() { long[] inputArray = new long[] { Long.MIN_VALUE, 0 }; double avgNumberOfBitsPerValue = 33.5; // BitEfficient stores '0' with 1 bit, the MIN_VALUE (special case!) with 64, // makes a avg of 32.5; additional 1 bit length encoding. assertRatio(inputArray, avgNumberOfBitsPerValue); } @Test public void withMinValueZeroPlus1Test() { long[] inputArray = new long[] { Long.MIN_VALUE + 1, 0 }; double avgNumberOfBitsPerValue = 65.; // BitEfficient does not use special case for MIN_VALUE+1 -> both 0 and // MIN_VALUE+1 are represented with 64 bits, additional 1 bit length assertRatio(inputArray, avgNumberOfBitsPerValue); } @Test public void withMaxValueZeroTest() { long[] inputArray = new long[] { 0, Long.MAX_VALUE }; double avgNumberOfBitsPerValue = 64.; assertRatio(inputArray, avgNumberOfBitsPerValue); } @Test public void withMinusOneToOneTest() { long[] inputArray = new long[] { -1, 0, 1 }; double avgNumberOfBitsPerValue = 3.; assertRatio(inputArray, avgNumberOfBitsPerValue); } @Test public void threeZeros() { long[] inputArray = new long[] { 0, 0, 0, 0, 1 }; int newLengthOfArrays = 2; // both "count" and "value" array have 2 entries. double avgNumberOfBitsPerValue = newLengthOfArrays * 4. / inputArray.length; // 1 bit value, 3 bits length assertRatio(inputArray, avgNumberOfBitsPerValue); } /** * Assert compression ratio */ private void assertRatio(long[] inputArray, double avgNumberOfBitsPerValue) { TransitiveCompressionRatioCalculator calculator = new TransitiveCompressionRatioCalculator() { @Override public double calculateTransitiveCompressionRatio(long min, long secondMin, long max, long size) { int numberOfMinValue = 0; if (min == Long.MIN_VALUE) { numberOfMinValue++; min = secondMin; } return BitEfficientLongArray.calculateApproxCompressionRatio(min, max, (int) size, numberOfMinValue); } }; RunLengthLongArray longArray = new RunLengthLongArray(); double ratioSorted = longArray.expectedCompressionRatio(inputArray, true, calculator); double ratioUnsorted = longArray.expectedCompressionRatio(inputArray, false, calculator); Assert.assertEquals(ratioUnsorted, ratioSorted, 0.001, "Sorted ratio should be equal to unsorted"); Assert.assertEquals(ratioUnsorted, avgNumberOfBitsPerValue / 64., 0.001, "Expected different ratio"); } }