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 := &current[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 := &current[i]
    44  		mzeros.Encode(enc, uint(cube.Interacting^1))
    45  	}
    46  
    47  	for _, i := range items {
    48  		cube, base := &current[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 := &current[i]
   107  		cube.Interacting = int32(mzeros.Decode(dec) ^ 1)
   108  	}
   109  
   110  	for _, i := range items {
   111  		cube, base := &current[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  }