From aff58aa75e9c4599e74198a1f3c779cefc2f3aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Sat, 1 Oct 2022 15:30:15 +0800 Subject: [PATCH] finish dec128blk1 --- decode.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++ decode_test.go | 22 ++++++++++++++++++ encode.go | 4 ++-- uint128be.go | 27 ++++++++++++++++++++++ uint128be_test.go | 5 +++- 5 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 decode_test.go diff --git a/decode.go b/decode.go index 45b9fc7..1051725 100644 --- a/decode.go +++ b/decode.go @@ -1,5 +1,63 @@ package unibase2n +import ( + "encoding/binary" +) + func (bs Base) Decode(data []byte) []byte { return nil } + +// dec128blk1 for bit 1 +// len(in)>0, len(in)%16==0, len(out)==len(in)/16 +func dec128blk1(mask uint128be, in, out []byte) { + for i := range out { + c := i * 16 + n := readuint128be(in[c : c+16]) + one := u128one + n.subeq(mask) + sum := n.and(one) + n.shreq(16 - 1) + one.shleq(1) + sum.oreq(n.and(one)) + n.shreq(16 - 1) + one.shleq(1) + sum.oreq(n.and(one)) + n.shreq(16 - 1) + one.shleq(1) + sum.oreq(n.and(one)) + n.shreq(16 - 1) + one.shleq(1) + sum.oreq(n.and(one)) + n.shreq(16 - 1) + one.shleq(1) + sum.oreq(n.and(one)) + n.shreq(16 - 1) + one.shleq(1) + sum.oreq(n.and(one)) + n.shreq(16 - 1) + one.shleq(1) + sum.oreq(n.and(one)) + out[i] = uint8(sum.b) + } +} + +// dec64blk2 for bit 2 +// len(in)!=0, len(out)==len(in)/8 +func dec64blk2(mask uint64, in, out []byte) { + for i, n := range in { + c := i * 8 + x := (uint64(n)<<42 | uint64(n)<<28 | uint64(n)<<14 | uint64(n)) & 0x00030003_00030003 + binary.BigEndian.PutUint64(out[c:c+8], x+mask) + } +} + +// dec32blk4 for bit 4 +// len(in)!=0, len(out)==len(in)/4 +func dec32blk4(mask uint32, in, out []byte) { + for i, n := range in { + c := i * 4 + x := (uint32(n)<<12 | uint32(n)) & 0x000f000f + binary.BigEndian.PutUint32(out[c:c+4], x+mask) + } +} diff --git a/decode_test.go b/decode_test.go new file mode 100644 index 0000000..96ffbe5 --- /dev/null +++ b/decode_test.go @@ -0,0 +1,22 @@ +package unibase2n + +import ( + "math/rand" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDec128blk1(t *testing.T) { + var in, tmp [32]byte + _, err := rand.Read(in[:]) + if err != nil { + t.Fatal(err) + } + n, _ := Base{bit: 1}.EncodeLen(32) + out := make([]byte, n) + enc16blk1(0x2333, in[:], out) + t.Log(out) + dec128blk1(uint128be{0x2333233323332333, 0x2333233323332333}, out[:], tmp[:]) + assert.Equal(t, in, tmp) +} diff --git a/encode.go b/encode.go index e99af75..48062f5 100644 --- a/encode.go +++ b/encode.go @@ -57,7 +57,7 @@ func enc16blk1(mask uint16, in, out []byte) { func enc64blk2(mask uint64, in, out []byte) { for i, n := range in { c := i * 8 - x := (uint64(n)<<42 | uint64(n)<<28 | uint64(n)<<14 | uint64(n)) & 0x30003_00030003 + x := (uint64(n)<<42 | uint64(n)<<28 | uint64(n)<<14 | uint64(n)) & 0x00030003_00030003 binary.BigEndian.PutUint64(out[c:c+8], x+mask) } } @@ -67,7 +67,7 @@ func enc64blk2(mask uint64, in, out []byte) { func enc32blk4(mask uint32, in, out []byte) { for i, n := range in { c := i * 4 - x := (uint32(n)<<12 | uint32(n)) & 0xf000f + x := (uint32(n)<<12 | uint32(n)) & 0x000f000f binary.BigEndian.PutUint32(out[c:c+4], x+mask) } } diff --git a/uint128be.go b/uint128be.go index 162f02c..0e837f7 100644 --- a/uint128be.go +++ b/uint128be.go @@ -12,6 +12,11 @@ type uint128be struct { b uint64 } +var ( + u128minusone = uint128be{0xffffffff_ffffffff, 0xffffffff_ffffffff} + u128one = uint128be{0, 1} +) + func readuint128be(b []byte) uint128be { if len(b) < 16 { b = append(b, make([]byte, 16-len(b))...) @@ -29,6 +34,20 @@ func (num *uint128be) addeq(n uint128be) { return } +func (num *uint128be) subeq(n uint128be) { + var b uint64 + num.b, b = bits.Sub64(num.b, n.b, 0) + num.a, _ = bits.Sub64(num.a, n.a, b) + return +} + +func (num uint128be) sub(n uint128be) (r uint128be) { + var b uint64 + r.b, b = bits.Sub64(num.b, n.b, 0) + r.a, _ = bits.Sub64(num.a, n.a, b) + return +} + // shreq only supports shifting 1 ~ 63 bits func (num *uint128be) shreq(c uint8) { mask := uint64(1)<> c) } +// shreq only supports shifting 1 ~ 63 bits +func (num *uint128be) shleq(c uint8) { + mask := (uint64(1)<> (64 - c) + num.b = num.b << c + num.a = bout | (num.a << c) +} + func (num *uint128be) andeq(n uint128be) { num.a &= n.a num.b &= n.b diff --git a/uint128be_test.go b/uint128be_test.go index 8b93dcd..2f12359 100644 --- a/uint128be_test.go +++ b/uint128be_test.go @@ -11,6 +11,7 @@ func TestUint128be(t *testing.T) { zero := readuint128be(make([]byte, 16)) one := readuint128be([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) num := readuint128be(buf[:]) + assert.Equal(t, zero.sub(one), num) num.addeq(one) assert.Equal(t, num, zero) num.addeq(readuint128be([]byte{0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef})) @@ -22,7 +23,9 @@ func TestUint128be(t *testing.T) { num.shreq(32) assert.Equal(t, num, uint128be{0x0000000000000012, 0x34567890abcdef12}) assert.Equal(t, num.String(), "0x1234567890abcdef12") - num.shreq(1) + num.shleq(8) + assert.Equal(t, num, uint128be{0x00000000000001234, 0x567890abcdef1200}) + num.shreq(9) // 因为 num.a 低 1 位为 0 所以可以成功 assert.Equal(t, num, uint128be{0x0000000000000012 >> 1, 0x34567890abcdef12 >> 1}) num.shreq(7)