1 /***********************************************************************
2   This file is part of HA, a general purpose file archiver.
3   Copyright (C) 1995 Harri Hirvola
4 
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 ************************************************************************
19 	HA arithmetic coder
20 ***********************************************************************/
21 
22 /***********************************************************************
23 This file contains some small changes made by Nico de Vries (AIP-NL)
24 allowing it to be compiled with Borland C++ 3.1.
25 ***********************************************************************/
26 
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include "ha.h"
31 #include "haio.h"
32 #include "acoder.h"
33 
34 static U16B h,l,v;
35 static S16B s;
36 static S16B gpat,ppat;
37 
38 /***********************************************************************
39   Bit I/O
40 ***********************************************************************/
41 
42 #define putbit(b) 	{ ppat<<=1;				\
43 			  if (b) ppat|=1;			\
44 			  if (ppat&0x100) {			\
45 				putbyte(ppat&0xff);		\
46 				ppat=1;				\
47 			  }					\
48 			}
49 
50 
51 #define getbit(b) 	{ gpat<<=1;				\
52 			  if (!(gpat&0xff)) {			\
53 				gpat=getbyte();			\
54 				if (gpat&0x100) gpat=0x100;	\
55 				else {				\
56 					gpat<<=1;		\
57 					gpat|=1;		\
58 				}				\
59 			  }					\
60 			  b|=(gpat&0x100)>>8;			\
61 			}
62 
63 
64 /***********************************************************************
65   Arithmetic encoding
66 ***********************************************************************/
67 
68 #ifndef __BORLANDC__
69 
ac_out(U16B low,U16B high,U16B tot)70 void ac_out(U16B low, U16B high, U16B tot) {
71 
72     register U32B r;
73 
74     r=(U32B)(h-l)+1;
75     h=(U16B)(r*high/tot-1)+l;
76     l+=(U16B)(r*low/tot);
77     if (!((h^l)&0x8000)) {
78 	putbit(l&0x8000);
79 	while(s) {
80 	    --s;
81 	    putbit(~l&0x8000);
82 	}
83 	l<<=1;
84 	h<<=1;
85 	h|=1;
86 	while (!((h^l)&0x8000)) {
87 	    putbit(l&0x8000);
88 	    l<<=1;
89 	    h<<=1;
90 	    h|=1;
91 	}
92     }
93     while ((l&0x4000)&&!(h&0x4000)) {
94 	++s;
95 	l<<=1;
96 	l&=0x7fff;
97 	h<<=1;
98 	h|=0x8001;
99     }
100 }
101 
102 #else
103 
ac_out(U16B low,U16B high,U16B tot)104 void ac_out(U16B low, U16B high, U16B tot) {
105 
106     asm {
107 	mov ax,h
108 	mov bx,l
109 	sub ax,bx
110 	add ax,1
111 	mov cx,ax
112         jc  aco0
113 	mul high
114         jmp aco1
115     }
116 aco0:
117     asm {
118         mov dx,high
119     }
120 aco1:
121     asm {
122         cmp dx,tot
123 	je  aco2
124         div tot
125         sub ax,1
126         jmp aco3
127     }
128 aco2:
129     asm {
130 	mov ax,0xffff
131     }
132 aco3:
133     asm {
134         add ax,bx
135 	mov h,ax
136 	mov ax,cx
137 	cmp ax,0
138         je  aco4
139         mul low
140         jmp aco5
141     }
142 aco4:
143     asm {
144         mov dx,low
145     }
146 aco5:
147     asm {
148 	div tot
149 	add l,ax
150     }
151     if (!((h^l)&0x8000)) {
152 	putbit(l&0x8000);
153 	while(s) {
154 	    --s;
155 	    putbit(~l&0x8000);
156 	}
157 	l<<=1;
158 	h<<=1;
159 	h|=1;
160 	while (!((h^l)&0x8000)) {
161 	    putbit(l&0x8000);
162 	    l<<=1;
163 	    h<<=1;
164 	    h|=1;
165 	}
166     }
167     while ((l&0x4000)&&!(h&0x4000)) {
168 	++s;
169 	l<<=1;
170 	l&=0x7fff;
171 	h<<=1;
172 	h|=0x8001;
173     }
174 }
175 
176 #endif
177 
ac_init_encode(void)178 void ac_init_encode(void) {
179 
180     h=0xffff;
181     l=s=0;
182     ppat=1;
183 }
184 
ac_end_encode(void)185 void ac_end_encode(void) {
186 
187     ++s;
188     putbit(l&0x4000);
189     while (s--) {
190 	putbit(~l&0x4000);
191     }
192     if (ppat==1) {
193 	flush();
194 	return;
195     }
196     while(!(ppat&0x100)) ppat<<=1;
197     putbyte(ppat&0xff);
198     flush();
199 }
200 
201 
202 /***********************************************************************
203   Arithmetic decoding
204 ***********************************************************************/
205 
206 #ifndef __BORLANDC__
207 
ac_in(U16B low,U16B high,U16B tot)208 void ac_in(U16B low, U16B high, U16B tot) {
209 
210     register U32B r;
211 
212     r=(U32B)(h-l)+1;
213     h=(U16B)(r*high/tot-1)+l;
214     l+=(U16B)(r*low/tot);
215     while (!((h^l)&0x8000)) {
216 	l<<=1;
217 	h<<=1;
218 	h|=1;
219 	v<<=1;
220 	getbit(v);
221     }
222     while ((l&0x4000)&&!(h&0x4000)) {
223 	l<<=1;
224 	l&=0x7fff;
225 	h<<=1;
226 	h|=0x8001;
227 	v<<=1;
228 	v^=0x8000;
229 	getbit(v);
230     }
231 }
232 
ac_threshold_val(U16B tot)233 U16B ac_threshold_val(U16B tot) {
234 
235     register U32B r;
236 
237     r=(U32B)(h-l)+1;
238     return (U16B)((((U32B)(v-l)+1)*tot-1)/r);
239 }
240 
241 #else
242 
ac_in(U16B low,U16B high,U16B tot)243 void ac_in(U16B low, U16B high, U16B tot) {
244 
245     asm {
246 	mov ax,h
247 	mov bx,l
248 	sub ax,bx
249 	add ax,1
250 	mov cx,ax
251         jc  aci0
252 	mul high
253         jmp aci1
254     }
255 aci0:
256     asm {
257         mov dx,high
258     }
259 aci1:
260     asm {
261         cmp dx,tot
262 	je  aci2
263         div tot
264         sub ax,1
265         jmp aci3
266     }
267 aci2:
268     asm {
269 	mov ax,0xffff
270     }
271 aci3:
272     asm {
273         add ax,bx
274 	mov h,ax
275 	mov ax,cx
276 	cmp ax,0
277         je  aci4
278         mul low
279         jmp aci5
280     }
281 aci4:
282     asm {
283         mov dx,low
284     }
285 aci5:
286     asm {
287 	div tot
288 	add l,ax
289     }
290     while (!((h^l)&0x8000)) {
291 	l<<=1;
292 	h<<=1;
293 	h|=1;
294 	v<<=1;
295 	getbit(v);
296     }
297     while ((l&0x4000)&&!(h&0x4000)) {
298 	l<<=1;
299 	l&=0x7fff;
300 	h<<=1;
301 	h|=0x8001;
302 	v<<=1;
303 	v^=0x8000;
304 	getbit(v);
305     }
306 }
307 
ac_threshold_val(U16B tot)308 U16B ac_threshold_val(U16B tot) {
309 
310     U16B rv;
311 
312     asm {
313 	mov ax,h
314 	sub ax,l
315 	add ax,1
316 	jc  atv1
317 	mov cx,ax
318 	mov ax,v
319 	sub ax,l
320 	inc ax
321 	mul [tot]
322 	sub ax,1
323 	sbb dx,0
324 	div cx
325 	mov rv,ax
326 	jmp atv3
327     }
328 atv1:
329     asm {
330 	mov ax,v
331 	sub ax,l
332 	add ax,1
333 	jc  atv2
334 	mul [tot]
335 	sub ax,1
336 	sbb dx,0
337 	mov rv,dx
338 	jmp atv3
339     }
340 atv2:
341     asm {
342 	mov ax,tot
343 	dec ax
344 	mov rv,dx
345     }
346 atv3:
347     return rv;
348 }
349 
350 #endif
351 
ac_init_decode(void)352 void ac_init_decode(void) {
353 
354     h=0xffff;
355     l=0;
356     gpat=0;
357     v=getbyte()<<8;
358     v|=0xff&getbyte();
359 }
360 
361