/* * Copyright 2005-2014, martin isenburg, rapidlasso - fast tools to catch reality * * This is free software; you can redistribute and/or modify it under the * terms of the GNU Lesser General Licence as published by the Free Software * Foundation. See the LICENSE.txt file for more information. * * This software is distributed WITHOUT ANY WARRANTY and without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ package com.revolsys.elevation.cloud.las.zip; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - // Fast arithmetic coding implementation - // -> 32-bit variables, 32-bit product, periodic updates, table decoding - // - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - // Version 1.00 - April 25, 2004 - // - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - // WARNING - // ========= - // - // The only purpose of this program is to demonstrate the basic principles - // of arithmetic coding. It is provided as is, without any express or - // implied warranty, without even the warranty of fitness for any particular - // purpose, or that the implementations are correct. - // - // Permission to copy and redistribute this code is hereby granted, provided - // that this warning and copyright notices are not removed or altered. - // - // Copyright (c) 2004 by Amir Said (said@ieee.org) & - // William A. Pearlman (pearlw@ecse.rpi.edu) - // - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - // A description of the arithmetic coding method used here is available in - // - // Lossless Compression Handbook, ed. K. Sayood - // Chapter 5: Arithmetic Coding (A. Said), pp. 101-152, Academic Press, 2003 - // - // A. Said, Introduction to Arithetic Coding Theory and Practice - // HP Labs report HPL-2004-76 - http://www.hpl.hp.com/techreports/ - // - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public class ArithmeticModel implements ArithmeticConstants { public static void initSymbolModel(final ArithmeticModel m) { ArithmeticModel.initSymbolModel(m, null); } public static void initSymbolModel(final ArithmeticModel model, final int[] table) { if (model != null) { model.init(table); } } public static void initSymbolModels(final ArithmeticModel... models) { for (final ArithmeticModel model : models) { if (model != null) { model.init(null); } } } private final boolean compress; int[] distribution; int[] symbolCount; int[] decoderTable; int totalCount; int updateCycle; int symbolsUntilUpdate; final int symbols; int lastSymbol; int tableSize; int tableShift; public ArithmeticModel(final int symbols, final boolean compress) { this.symbols = symbols; this.compress = compress; } public int init() { return init(null); } public int init(final int[] table) { if (this.distribution == null) { if (this.symbols < 2 || this.symbols > 1 << 11) { return -1; // invalid number of symbols } this.lastSymbol = this.symbols - 1; if (!this.compress && this.symbols > 16) { int table_bits = 3; while (this.symbols > 1 << table_bits + 2) { ++table_bits; } this.tableSize = 1 << table_bits; this.tableShift = DM_LENGTH_SHIFT - table_bits; this.distribution = new int[this.symbols]; this.decoderTable = new int[this.tableSize + 2]; } else { // small alphabet: no table needed this.decoderTable = null; this.tableSize = this.tableShift = 0; this.distribution = new int[this.symbols]; } this.symbolCount = new int[this.symbols]; } this.totalCount = 0; this.updateCycle = this.symbols; if (table != null) { for (int k = 0; k < this.symbols; k++) { this.symbolCount[k] = table[k]; } } else { for (int k = 0; k < this.symbols; k++) { this.symbolCount[k] = 1; } } update(); this.symbolsUntilUpdate = this.updateCycle = this.symbols + 6 >>> 1; return 0; } void update() { // halve counts when a threshold is reached final int[] symbolCount = this.symbolCount; if ((this.totalCount += this.updateCycle) > DM_MAX_COUNT) { this.totalCount = 0; for (int n = 0; n < this.symbols; n++) { this.totalCount += symbolCount[n] = symbolCount[n] + 1 >>> 1; } } // compute cumulative distribution, decoder table int k, sum = 0, s = 0; final int scale = Integer.divideUnsigned(0x80000000, this.totalCount); final int[] distribution = this.distribution; if (this.compress || this.tableSize == 0) { for (k = 0; k < this.symbols; k++) { distribution[k] = scale * sum >>> 31 - DM_LENGTH_SHIFT; sum += symbolCount[k]; } } else { final int[] decoderTable2 = this.decoderTable; for (k = 0; k < this.symbols; k++) { distribution[k] = scale * sum >>> 31 - DM_LENGTH_SHIFT; sum += symbolCount[k]; final int w = distribution[k] >>> this.tableShift; while (s < w) { decoderTable2[++s] = k - 1; } } decoderTable2[0] = 0; while (s <= this.tableSize) { decoderTable2[++s] = this.symbols - 1; } } // set frequency of model updates this.updateCycle = 5 * this.updateCycle >>> 2; final int max_cycle = this.symbols + 6 << 3; if (Integer.compareUnsigned(this.updateCycle, max_cycle) > 0) { this.updateCycle = max_cycle; } this.symbolsUntilUpdate = this.updateCycle; } void update(final int symbol) { this.symbolCount[symbol]++; if (--this.symbolsUntilUpdate == 0) { update(); } } }