github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/physicscompress/physics/encoding.go (about) 1 package physics 2 3 import ( 4 "fmt" 5 6 "github.com/egonelbre/exp/bit" 7 "github.com/egonelbre/exp/coder/arith" 8 ) 9 10 // encodes zeros well 11 func mZeros() arith.Model { 12 return &arith.Shift2{P0: 0x34a, I0: 0x1, P1: 0xd0, I1: 0x5} 13 } 14 15 func mValues(nbits uint) arith.Model { 16 return arith.NewTree(nbits, func() arith.Model { 17 return &arith.Shift2{P0: 0x438, I0: 0x3, P1: 0x61a, I1: 0x1} 18 }) 19 } 20 21 var totalbits = 0 22 23 func (s *State) Encode() []byte { 24 enc := arith.NewEncoder() 25 26 historic := s.Historic().Cubes 27 baseline := s.Baseline().Cubes 28 current := s.Current().Cubes 29 30 mzeros := mZeros() 31 items := []int{} 32 for i := range current { 33 cube, base := ¤t[i], &baseline[i] 34 if *cube == *base { 35 mzeros.Encode(enc, 0) 36 } else { 37 mzeros.Encode(enc, 1) 38 items = append(items, i) 39 } 40 } 41 42 for _, i := range items { 43 cube := ¤t[i] 44 mzeros.Encode(enc, uint(cube.Interacting^1)) 45 } 46 47 for _, i := range items { 48 cube, base := ¤t[i], &baseline[i] 49 v := uint(cube.Largest ^ base.Largest) 50 mzeros.Encode(enc, v&1) 51 mzeros.Encode(enc, v>>1) 52 } 53 54 items6 := Index6(items, len(baseline)) 55 SortByZ(items6, Delta6(historic, baseline)) 56 get6 := Extra6(historic, baseline, current) 57 58 max := uint64(0) 59 for _, i := range items6 { 60 ext := uint64(bit.ZEncode(int64(get6(i)))) 61 if max < ext { 62 max = ext 63 } 64 } 65 66 if max == 0 { 67 mzeros.Encode(enc, 1) 68 enc.Close() 69 return enc.Bytes() 70 } 71 72 nbits := bit.ScanRight(max) + 1 73 for i := 0; i < int(nbits); i += 1 { 74 mzeros.Encode(enc, 0) 75 } 76 mzeros.Encode(enc, 1) 77 78 mvalues := mValues(nbits) 79 for _, i := range items6 { 80 val := uint(bit.ZEncode(int64(get6(i)))) 81 mvalues.Encode(enc, val) 82 } 83 84 enc.Close() 85 return enc.Bytes() 86 } 87 88 func (s *State) Decode(snapshot []byte) { 89 dec := arith.NewDecoder(snapshot) 90 91 s.Current().Assign(s.Baseline()) 92 historic := s.Historic().Cubes 93 baseline := s.Baseline().Cubes 94 current := s.Current().Cubes 95 96 mzeros := mZeros() 97 98 items := []int{} 99 for i := range current { 100 if mzeros.Decode(dec) == 1 { 101 items = append(items, i) 102 } 103 } 104 105 for _, i := range items { 106 cube := ¤t[i] 107 cube.Interacting = int32(mzeros.Decode(dec) ^ 1) 108 } 109 110 for _, i := range items { 111 cube, base := ¤t[i], &baseline[i] 112 v0, v1 := mzeros.Decode(dec), mzeros.Decode(dec) 113 cube.Largest = base.Largest ^ int32(v1<<1|v0) 114 } 115 116 items6 := Index6(items, len(baseline)) 117 SortByZ(items6, Delta6(historic, baseline)) 118 set6 := SetExtra6(historic, baseline, current) 119 120 nbits := uint(0) 121 for mzeros.Decode(dec) == 0 { 122 nbits += 1 123 } 124 125 if nbits == 0 { 126 for _, i := range items6 { 127 set6(i, 0) 128 } 129 return 130 } 131 132 mvalues := mValues(nbits) 133 for _, i := range items6 { 134 z := mvalues.Decode(dec) 135 v := bit.ZDecode(uint64(z)) 136 set6(i, int32(v)) 137 } 138 } 139 140 func Index6(index []int, N int) []int { 141 r := make([]int, 0, len(index)*6) 142 for _, v := range index { 143 r = append(r, v, v+N, v+N*2, v+N*3, v+N*4, v+N*5) 144 } 145 return r 146 } 147 148 func Value6(base []Cube) func(i int) int32 { 149 N := len(base) 150 return func(i int) int32 { 151 k := i % N 152 switch i / N { 153 case 0: 154 return base[k].A 155 case 1: 156 return base[k].B 157 case 2: 158 return base[k].C 159 case 3: 160 return base[k].X 161 case 4: 162 return base[k].Y 163 case 5: 164 return base[k].Z 165 default: 166 panic("invalid") 167 } 168 } 169 } 170 171 func Delta6(hist, base []Cube) func(i int) int32 { 172 N := len(base) 173 return func(i int) int32 { 174 k := i % N 175 switch i / N { 176 case 0: 177 return hist[k].A - base[k].A 178 case 1: 179 return hist[k].B - base[k].B 180 case 2: 181 return hist[k].C - base[k].C 182 case 3: 183 return hist[k].X - base[k].X 184 case 4: 185 return hist[k].Y - base[k].Y 186 case 5: 187 return hist[k].Z - base[k].Z 188 default: 189 panic("invalid") 190 } 191 } 192 } 193 194 func Extra6(hist, base, cur []Cube) func(i int) int32 { 195 N := len(base) 196 return func(i int) int32 { 197 k := i % N 198 switch i / N { 199 case 0: 200 return cur[k].A - base[k].A + (hist[k].A - base[k].A) 201 case 1: 202 return cur[k].B - base[k].B + (hist[k].B - base[k].B) 203 case 2: 204 return cur[k].C - base[k].C + (hist[k].C - base[k].C) 205 case 3: 206 return cur[k].X - base[k].X + (hist[k].X - base[k].X) 207 case 4: 208 return cur[k].Y - base[k].Y + (hist[k].Y - base[k].Y) 209 case 5: 210 return cur[k].Z - base[k].Z + (hist[k].Z - base[k].Z) 211 default: 212 panic("invalid") 213 } 214 } 215 } 216 217 func SetExtra6(hist, base, cur []Cube) func(i int, v int32) { 218 N := len(base) 219 return func(i int, v int32) { 220 k := i % N 221 switch i / N { 222 case 0: 223 cur[k].A = v + base[k].A - (hist[k].A - base[k].A) 224 case 1: 225 cur[k].B = v + base[k].B - (hist[k].B - base[k].B) 226 case 2: 227 cur[k].C = v + base[k].C - (hist[k].C - base[k].C) 228 case 3: 229 cur[k].X = v + base[k].X - (hist[k].X - base[k].X) 230 case 4: 231 cur[k].Y = v + base[k].Y - (hist[k].Y - base[k].Y) 232 case 5: 233 cur[k].Z = v + base[k].Z - (hist[k].Z - base[k].Z) 234 default: 235 panic("invalid") 236 } 237 } 238 } 239 240 func SameBools(a, b []bool) { 241 if len(a) != len(b) { 242 panic("different length") 243 } 244 245 as := BoolsStr(a) 246 bs := BoolsStr(b) 247 if as != bs { 248 fmt.Println("---") 249 fmt.Println(as) 250 fmt.Println(bs) 251 fmt.Println("---") 252 } 253 } 254 255 func BoolsStr(a []bool) string { 256 r := make([]byte, 0, len(a)) 257 for _, v := range a { 258 if v { 259 r = append(r, '.') 260 } else { 261 r = append(r, 'X') 262 } 263 } 264 return string(r) 265 }