summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-reader/arith_d.cpp
blob: c43d697d05e64b2fb64c5f972161275044cb7b72 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* décodage arithmétique 
 * optimisé pour une arithmétique 16 bits
 */
#include <stdlib.h>
#include "arith.h"


/*
 * Initialisation du décodeur.
 * bufsize doit être multiple de 2 et supérieur à 4
 */

void ArithClass::Arith_DecodeInit(PPM_ReadBuf* readbuf,UCHAR *buf,UINT bufsize) {

	 /* gestion buffer */
	 
	 ainbuf=buf;
	 ainbufsize=bufsize;
	 areadbuf=readbuf;
	 aendinbuf=ainbuf+ainbufsize;
	 areadbuf->readbuf(ainbuf,ainbufsize);
	 apinbuf=ainbuf;
	 
	 /* intervalle et position dans l'intervalle */
	 alow=0;
	 ahigh=0xFFFF;
	 avalue=(*apinbuf++)<<8;
	 avalue|=(*apinbuf++);
	 
	 /* remplissage du buffer 16 bits */
	 
	 abitbuf=(*apinbuf++)<<8;
	 abitbuf|=(*apinbuf++);
	 abitcnt=16;
}

#define DIV16(a,b)		( (UINT)(a)/(UINT)(b) )
#define MUL16(a,b)		( (UINT)(a)*(UINT)(b) )

/*
 * Décodage: première étape
 */

UINT ArithClass::Arith_DecodeVal(UINT asize)  {
	 USHORT range,c;

	 range=ahigh-alow+1;
	 c=avalue-alow+1;
	 if (range!=0) {
			if (c==0) return DIV16(((UINT)asize<<16)-1,range);
			else return DIV16(MUL16(c,asize)-1,range);
	 } else {
			if (c==0) return (asize-1);
			else return (MUL16(c,asize)-1)>>16;
	 }
}

/*
 * Décodage: deuxième étape
 */

void ArithClass::Arith_Decode(UINT amin,UINT amax,UINT asize) {
	 USHORT range;

	 range = ahigh - alow;
	 if (amax!=asize) ahigh=alow+DIV16(MUL16(range,amax)+amax,asize)-1;
	 if (amin!=0) alow+=DIV16(MUL16(range,amin)+amin,asize);
	 for ( ; ; ) {
			if ( alow>=0x4000 && ahigh<0xC000 ) {
				 avalue -= 0x4000;  alow -= 0x4000;  ahigh -= 0x4000;
			} else if ( ahigh>=0x8000 && alow<0x8000 ) break;
			
			alow+=alow;
			ahigh+=ahigh+1;
			avalue=(avalue<<1)|( (abitbuf&0x8000)!=0 );
			abitbuf<<=1;
			if ( (--abitcnt)==0 ) {
				 abitbuf=(*apinbuf++)<<8;
				 abitbuf|=(*apinbuf++);
				 abitcnt=16;
				 if (apinbuf>=aendinbuf) {
						areadbuf->readbuf(ainbuf,ainbufsize);
						apinbuf=ainbuf;
				 }
			}
	 }
}

/*
 * fin du décodage: rien à faire
 */

void ArithClass::Arith_DecodeEnd(void) {
}