ArithmeticCoding
0.0.0a
Arithmetic coding in C
|
00001 #include "stream.h" 00002 00003 #include <stdint.h> // for fixed width integer types 00004 #include <stdlib.h> // for size_t 00005 #include <stdio.h> // for exception logging 00006 #include <string.h> // for memset 00007 00008 typedef uint8_t u8; 00009 typedef uint16_t u16; 00010 typedef uint32_t u32; 00011 typedef uint64_t u64; 00012 typedef int8_t i8; 00013 typedef int16_t i16; 00014 typedef int32_t i32; 00015 typedef int64_t i64; 00016 00017 #define ENDL "\n" 00018 #define TRY(e) \ 00019 do{ if(!(e)) {\ 00020 printf("%s(%d):"ENDL "\t%s"ENDL "\tExpression evaluated as false."ENDL, \ 00021 __FILE__,__LINE__,#e); \ 00022 goto Error; \ 00023 }} while(0) 00024 00025 #define SAFE_FREE(e) if(e) { free(e); (e)=NULL; } 00026 00027 static void maybe_init(stream_t *self) 00028 { if(!self->d) 00029 { memset(self,0,sizeof(*self)); 00030 TRY(self->d=malloc(self->nbytes=4096)); 00031 self->own=1; 00032 } 00033 return; 00034 Error: 00035 abort(); 00036 } 00037 00038 void attach(stream_t *self, void* d, size_t n) 00039 { if(self->own) SAFE_FREE(self->d); 00040 self->d = (u8*)d; 00041 self->own = 0; 00042 self->nbytes = n; 00043 maybe_init(self); 00044 } 00045 00046 void detach(stream_t *self, void **d, size_t *n) 00047 { if(d) *d = self->d; 00048 if(n) *n = self->ibyte; 00049 memset(self,0,sizeof(*self)); 00050 } 00051 00052 static void maybe_resize(stream_t *s) 00053 { if(s->ibyte>=s->nbytes) 00054 TRY(s->d = realloc(s->d,s->nbytes=(1.2*s->ibyte+50))); 00055 return; 00056 Error: 00057 abort(); 00058 } 00059 00060 //printf("PUSH: [%llu] %llu %llu"ENDL,(u64)self->ibyte,(u64)v,(u64)(*(T*)(self->d+self->ibyte))); 00061 00062 #define DEFN_PUSH(T) \ 00063 void push_##T(stream_t *self, T v) \ 00064 { *(T*)(self->d+self->ibyte) = v; \ 00065 self->ibyte+=sizeof(T); \ 00066 maybe_resize(self); \ 00067 } 00068 DEFN_PUSH(u8); 00069 DEFN_PUSH(u16); 00070 DEFN_PUSH(u32); 00071 DEFN_PUSH(u64); 00072 DEFN_PUSH(i8); 00073 DEFN_PUSH(i16); 00074 DEFN_PUSH(i32); 00075 DEFN_PUSH(i64); 00076 00077 void push_u1(stream_t *self, u8 v) 00078 { 00079 self->mask = 1<<(7-self->ibit); // index from the high bit so we can use integer addition to do carries 00080 //set 00081 { u8 *w = self->d+self->ibyte, 00082 m = self->mask; 00083 *w = (*w & ~m) | (-(v) & m); 00084 } 00085 //inc 00086 if(self->ibit==7) 00087 { self->ibit=0; 00088 self->ibyte++; 00089 maybe_resize(self); 00090 self->d[self->ibyte]=0; // clear out the byte 00091 } else 00092 { self->ibit++; 00093 } 00094 } 00095 void push_u4(stream_t *self, u8 v) 00096 { 00097 self->mask = (self->ibit==0)?0xf0:0x0f ; // index from the high bit so we can use integer addition to do carries 00098 //set 00099 { u8 *w = self->d+self->ibyte, 00100 m = self->mask; 00101 *w ^= (*w^ (v<<(4-self->ibit)) )&m; 00102 } 00103 //inc 00104 if(self->ibit==4) 00105 { self->ibit=0; 00106 self->ibyte++; 00107 maybe_resize(self); 00108 self->d[self->ibyte]=0; // clear out the byte 00109 } else 00110 { self->ibit=4; 00111 } 00112 } 00113 00114 #define DEFN_POP(T) \ 00115 T pop_##T(stream_t *self) \ 00116 { T v; \ 00117 if(self->ibyte>=self->nbytes) return 0; \ 00118 v = *(T*)(self->d+self->ibyte); \ 00119 self->ibyte+=sizeof(T); \ 00120 return v; \ 00121 } 00122 DEFN_POP(u8); 00123 DEFN_POP(u16); 00124 DEFN_POP(u32); 00125 DEFN_POP(u64); 00126 DEFN_POP(i8); 00127 DEFN_POP(i16); 00128 DEFN_POP(i32); 00129 DEFN_POP(i64); 00130 00131 u8 pop_u1(stream_t *self) 00132 { u8 v,m; 00133 m = 1<<(7-self->ibit); 00134 v = 0; 00135 if(self->ibyte<self->nbytes) 00136 v = (self->d[self->ibyte] & m)==m; 00137 //inc 00138 self->ibit++; 00139 if(self->ibit>7) 00140 { self->ibit=0; 00141 self->ibyte++; 00142 } 00143 return v; 00144 } 00145 u8 pop_u4(stream_t *self) 00146 { u8 v,m; 00147 m = (self->ibit==0)?0xf0:0x0f; 00148 v = 0; 00149 if(self->ibyte<self->nbytes) 00150 v = (self->d[self->ibyte] & m)>>(4-self->ibit); 00151 //inc 00152 if(self->ibit==4) 00153 { self->ibit=0; 00154 self->ibyte++; 00155 } else 00156 self->ibit=4; 00157 return v; 00158 } 00159 00160 #define MAX_TYPE(T) static const T max_##T = (T)(-1) 00161 MAX_TYPE(u8); 00162 MAX_TYPE(u16); 00163 MAX_TYPE(u32); 00164 MAX_TYPE(u64); 00165 00166 #define DEFN_CARRY(T) \ 00167 void carry_##T(stream_t *self) \ 00168 { size_t n = (self->ibyte-1)/sizeof(T); \ 00169 while( ((T*)(self->d))[n]==max_##T ) \ 00170 ((T*)(self->d))[n--]=0; \ 00171 ((T*)(self->d))[n]++; \ 00172 } 00173 DEFN_CARRY(u8); 00174 DEFN_CARRY(u16); 00175 DEFN_CARRY(u32); 00176 DEFN_CARRY(u64); 00177 00178 void carry_u1(stream_t *self) 00179 { size_t ibyte=self->ibyte; // ibit = 0 is the high bit 00180 u8 *d = self->d; 00181 u8 s,c; 00182 ibyte -= (ibyte>0)&&(self->mask&1); // if ibyte has wrapped over, subtract one 00183 c=d[ibyte] + self->mask; // carry the ibits 00184 s=c<d[ibyte]; // overflow test 00185 d[ibyte]=c; 00186 if(s) // need to keep carrying 00187 { while(d[--ibyte]==255) 00188 d[ibyte]=0; // compliment all bits 00189 d[ibyte] += 1; // finish carrying 00190 } 00191 } 00192 void carry_u4(stream_t *self) 00193 { size_t ibyte=self->ibyte; // ibit = 0 is the high bit 00194 u8 *d = self->d; 00195 u8 s,c; 00196 u8 m = (self->ibit==0)?0x01:0x10; //if 0, last write was 0x0f, otherwise at 0xf0 00197 ibyte -= (ibyte>0)&&(self->mask==0x0f); // if ibyte has wrapped over, subtract one 00198 c=d[ibyte] + m; // carry 00199 s=c<d[ibyte]; // overflow test 00200 d[ibyte]=c; 00201 if(s) // need to keep carrying 00202 { while(d[--ibyte]==255) 00203 d[ibyte]=0; // compliment all bits 00204 d[ibyte] += 1; // finish carrying 00205 } 00206 }