/*
 * JFFS2 -- Journalling Flash File System, Version 2.
 *
 * Copyright (C) 2004 Patrik Kluba,
 *                    University of Szeged, Hungary
 *
 * For licensing information, see the file 'LICENCE' in the
 * jffs2 directory.
 *
 * $Id: compr_lzari.c,v 1.3 2004/06/23 16:34:39 havasi Exp $
 *
 */

/*
   Lempel-Ziv-Arithmetic coding compression module for jffs2
   Based on the LZARI source included in LDS (lossless datacompression sources)
*/

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */

/*
Original copyright follows:

**************************************************************
	LZARI.C -- A Data Compression Program
	(tab = 4 spaces)
**************************************************************
	4/7/1989 Haruhiko Okumura
	Use, distribute, and modify this program freely.
	Please send me your improved versions.
		PC-VAN		SCIENCE
		NIFTY-Serve	PAF01022
		CompuServe	74050,1022
**************************************************************

LZARI.C (c)1989 by Haruyasu Yoshizaki, Haruhiko Okumura, and Kenji Rikitake.
All rights reserved. Permission granted for non-commercial use.

*/

/*

	2004-02-18  pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
				Removed unused variables and fixed no return value

	2004-02-16  pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
				Initial release

*/


#include <config.h>
#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_JFFS2_LZO_LZARI)

#include <linux/stddef.h>
#include <jffs2/jffs2.h>


#define N			4096	/* size of ring buffer */
#define F			60	/* upper limit for match_length */
#define THRESHOLD		2	/* encode string into position and length
					   if match_length is greater than this */
#define NIL			N	/* index for root of binary search trees */

static unsigned char
		text_buf[N + F - 1];	/* ring buffer of size N,
			with extra F-1 bytes to facilitate string comparison */

/********** Arithmetic Compression **********/

/*  If you are not familiar with arithmetic compression, you should read
		I. E. Witten, R. M. Neal, and J. G. Cleary,
			Communications of the ACM, Vol. 30, pp. 520-540 (1987),
	from which much have been borrowed.  */

#define M   15

/*	Q1 (= 2 to the M) must be sufficiently large, but not so
	large as the unsigned long 4 * Q1 * (Q1 - 1) overflows.  */

#define Q1  (1UL << M)
#define Q2  (2 * Q1)
#define Q3  (3 * Q1)
#define Q4  (4 * Q1)
#define MAX_CUM (Q1 - 1)

#define N_CHAR  (256 - THRESHOLD + F)
	/* character code = 0, 1, ..., N_CHAR - 1 */

static unsigned long char_to_sym[N_CHAR], sym_to_char[N_CHAR + 1];
static unsigned long
	sym_freq[N_CHAR + 1],  /* frequency for symbols */
	sym_cum[N_CHAR + 1],   /* cumulative freq for symbols */
	position_cum[N + 1];   /* cumulative freq for positions */

static void StartModel(void)  /* Initialize model */
{
	unsigned long ch, sym, i;

	sym_cum[N_CHAR] = 0;
	for (sym = N_CHAR; sym >= 1; sym--) {
		ch = sym - 1;
		char_to_sym[ch] = sym;  sym_to_char[sym] = ch;
		sym_freq[sym] = 1;
		sym_cum[sym - 1] = sym_cum[sym] + sym_freq[sym];
	}
	sym_freq[0] = 0;  /* sentinel (!= sym_freq[1]) */
	position_cum[N] = 0;
	for (i = N; i >= 1; i--)
		position_cum[i - 1] = position_cum[i] + 10000 / (i + 200);
			/* empirical distribution function (quite tentative) */
			/* Please devise a better mechanism! */
}

static void UpdateModel(unsigned long sym)
{
	unsigned long c, ch_i, ch_sym;
	unsigned long i;
	if (sym_cum[0] >= MAX_CUM) {
		c = 0;
		for (i = N_CHAR; i > 0; i--) {
			sym_cum[i] = c;
			c += (sym_freq[i] = (sym_freq[i] + 1) >> 1);
		}
		sym_cum[0] = c;
	}
	for (i = sym; sym_freq[i] == sym_freq[i - 1]; i--) ;
	if (i < sym) {
		ch_i = sym_to_char[i];    ch_sym = sym_to_char[sym];
		sym_to_char[i] = ch_sym;  sym_to_char[sym] = ch_i;
		char_to_sym[ch_i] = sym;  char_to_sym[ch_sym] = i;
	}
	sym_freq[i]++;
	while (--i > 0) sym_cum[i]++;
	sym_cum[0]++;
}

static unsigned long BinarySearchSym(unsigned long x)
	/* 1      if x >= sym_cum[1],
	   N_CHAR if sym_cum[N_CHAR] > x,
	   i such that sym_cum[i - 1] > x >= sym_cum[i] otherwise */
{
	unsigned long i, j, k;

	i = 1;  j = N_CHAR;
	while (i < j) {
		k = (i + j) / 2;
		if (sym_cum[k] > x) i = k + 1;  else j = k;
	}
	return i;
}

unsigned long BinarySearchPos(unsigned long x)
	/* 0 if x >= position_cum[1],
	   N - 1 if position_cum[N] > x,
	   i such that position_cum[i] > x >= position_cum[i + 1] otherwise */
{
	unsigned long i, j, k;

	i = 1;  j = N;
	while (i < j) {
		k = (i + j) / 2;
		if (position_cum[k] > x) i = k + 1;  else j = k;
	}
	return i - 1;
}

static int Decode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long srclen,
					unsigned long dstlen)	/* Just the reverse of Encode(). */
{
	unsigned long i, r, j, k, c, range, sym;
	unsigned char *ip, *op;
	unsigned char *srcend = srcbuf + srclen;
	unsigned char *dstend = dstbuf + dstlen;
	unsigned char buffer = 0;
	unsigned char mask = 0;
	unsigned long low = 0;
	unsigned long high = Q4;
	unsigned long value = 0;

	ip = srcbuf;
	op = dstbuf;
	for (i = 0; i < M + 2; i++) {
		value *= 2;
		if ((mask >>= 1) == 0) {
			buffer = (ip >= srcend) ? 0 : *(ip++);
			mask = 128;
		}
		value += ((buffer & mask) != 0);
	}

	StartModel();
	for (i = 0; i < N - F; i++) text_buf[i] = ' ';
	r = N - F;

	while (op < dstend) {
		range = high - low;
		sym = BinarySearchSym((unsigned long)
				(((value - low + 1) * sym_cum[0] - 1) / range));
		high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
		low +=       (range * sym_cum[sym    ]) / sym_cum[0];
		for ( ; ; ) {
			if (low >= Q2) {
				value -= Q2;  low -= Q2;  high -= Q2;
			} else if (low >= Q1 && high <= Q3) {
				value -= Q1;  low -= Q1;  high -= Q1;
			} else if (high > Q2) break;
			low += low;  high += high;
			value *= 2;
			if ((mask >>= 1) == 0) {
				buffer = (ip >= srcend) ? 0 : *(ip++);
				mask = 128;
			}
			value += ((buffer & mask) != 0);
		}
		c = sym_to_char[sym];
		UpdateModel(sym);
		if (c < 256) {
			if (op >= dstend) return -1;
			*(op++) = c;
			text_buf[r++] = c;
			r &= (N - 1);
		} else {
			j = c - 255 + THRESHOLD;
			range = high - low;
			i = BinarySearchPos((unsigned long)
				(((value - low + 1) * position_cum[0] - 1) / range));
			high = low + (range * position_cum[i    ]) / position_cum[0];
			low +=       (range * position_cum[i + 1]) / position_cum[0];
			for ( ; ; ) {
				if (low >= Q2) {
					value -= Q2;  low -= Q2;  high -= Q2;
				} else if (low >= Q1 && high <= Q3) {
					value -= Q1;  low -= Q1;  high -= Q1;
				} else if (high > Q2) break;
				low += low;  high += high;
				value *= 2;
				if ((mask >>= 1) == 0) {
					buffer = (ip >= srcend) ? 0 : *(ip++);
					mask = 128;
				}
				value += ((buffer & mask) != 0);
			}
			i = (r - i - 1) & (N - 1);
			for (k = 0; k < j; k++) {
				c = text_buf[(i + k) & (N - 1)];
				if (op >= dstend) return -1;
				*(op++) = c;
				text_buf[r++] = c;
				r &= (N - 1);
			}
		}
	}
	return 0;
}

int lzari_decompress(unsigned char *data_in, unsigned char *cpage_out,
		      u32 srclen, u32 destlen)
{
    return Decode(data_in, cpage_out, srclen, destlen);
}
#endif
