func testWriteBigIntOrdering(t *testing.T) { buf := Buffer() WriteBigInt(big.NewInt(-10258176), buf) prev := string(buf.Bytes()) var i int64 for i = -10258175; i < 10258175; i++ { buf.Reset() WriteBigInt(big.NewInt(i), buf) cur := string(buf.Bytes()) if prev >= cur { t.Errorf("Lexicographical ordering failure for %d -- %q >= %q", i, prev, cur) } prev = cur } }
func writeBigInt(value *big.Int, buffer *bytes.Buffer, cutoff *big.Int) (positive bool) { if value.IsZero() { buffer.Write(zeroBase) return !value.RawNeg() } if !value.RawNeg() { positive = true if value.Cmp(cutoff) == -1 { encoding := []byte{'\x80', '\x01', '\x01'} mod := big.NewInt(0) div, mod := value.DivMod(value, bigint255, mod) encoding[2] = byte(mod.Int64()) + 1 if div.Sign() == 1 { div, mod = div.DivMod(div, bigint255, mod) encoding[1] = byte(mod.Int64()) + 1 if div.Sign() == 1 { encoding[0] = byte(div.Int64()) + 128 } } buffer.Write(encoding) } else { value = value.Sub(value, cutoff) buffer.WriteByte('\xff') left := big.NewInt(0) lead, left := value.DivMod(value, bigint255, left) var n int64 = 1 exp := big.NewInt(0) div := big.NewInt(0) for (div.Div(lead, exp.Exp(big.NewInt(253), big.NewInt(n), nil))).Sign() == 1 { n += 1 } buffer.WriteByte(byte(n) + 1) buffer.WriteByte('\xff') leadChars := make([]byte, 0) mod := big.NewInt(0) for { if lead.IsZero() { break } lead, mod = lead.DivMod(lead, bigint253, mod) leadChars = append(leadChars, byte(mod.Int64())+2) } lenLead := len(leadChars) if lenLead > 0 { for i := lenLead - 1; i >= 0; i-- { buffer.WriteByte(leadChars[i]) } } if left.Sign() == 1 { buffer.WriteByte('\x01') buffer.WriteByte(byte(left.Int64())) } } } else { value = value.Neg(value) if value.Cmp(cutoff) == -1 { encoding := []byte{'\x7f', '\xfe', '\xfe'} mod := big.NewInt(0) div, mod := value.DivMod(value, bigint255, mod) encoding[2] = 254 - byte(mod.Int64()) if div.Sign() == 1 { div, mod = div.DivMod(div, bigint255, mod) encoding[1] = 254 - byte(mod.Int64()) if div.Sign() == 1 { encoding[0] = 127 - byte(div.Int64()) } } buffer.Write(encoding) } else { value = value.Sub(value, cutoff) buffer.WriteByte('\x00') left := big.NewInt(0) lead, left := value.DivMod(value, bigint254, left) var n int64 = 1 exp := big.NewInt(0) div := big.NewInt(0) for (div.Div(lead, exp.Exp(big.NewInt(253), big.NewInt(n), nil))).Sign() == 1 { n += 1 } buffer.WriteByte(254 - byte(n)) buffer.WriteByte('\x00') leadChars := make([]byte, 0) mod := big.NewInt(0) for { if lead.IsZero() { break } lead, mod = lead.DivMod(lead, bigint253, mod) leadChars = append(leadChars, byte(253-mod.Int64())) } lenLead := len(leadChars) if lenLead > 0 { for i := lenLead - 1; i >= 0; i-- { buffer.WriteByte(leadChars[i]) } } if lenLead > 1 { buffer.WriteByte('\x00') } buffer.WriteByte('\xfe') if left.Sign() == 1 { buffer.WriteByte('\x01') buffer.WriteByte(254 - byte(left.Int64())) } else { buffer.WriteByte('\xfe') } } } return }
func testWriteBigInt(t *testing.T) { N := big.NewInt(8322944) buf := Buffer() WriteBigInt(N, buf) fmt.Printf("%q\n", string(buf.Bytes())) }
func encodeBigInt(value *big.Int, cutoff *big.Int) []byte { if value.IsZero() { return []byte{'\x80', '\x01', '\x01'} } if !value.IsNegative() { if value.Cmp(cutoff) == -1 { encoding := []byte{'\x80', '\x01', '\x01'} mod := big.NewInt(0) div, mod := value.DivMod(value, bigint255, mod) encoding[2] = byte(mod.Int64()) + 1 if div.Sign() == 1 { div, mod = div.DivMod(div, bigint255, mod) encoding[1] = byte(mod.Int64()) + 1 if div.Sign() == 1 { encoding[0] = byte(div.Int64()) + 128 } } return encoding } value = value.Sub(value, cutoff) encoding := []byte{'\xff'} left := big.NewInt(0) lead, left := value.DivMod(value, bigint255, left) var n int64 = 1 exp := big.NewInt(0) div := big.NewInt(0) for (div.Div(lead, exp.Exp(big.NewInt(253), big.NewInt(n), nil))).Sign() == 1 { n += 1 } encoding = append(encoding, byte(n)+1, '\xff') leadChars := make([]byte, 0) mod := big.NewInt(0) for { if lead.IsZero() { break } lead, mod = lead.DivMod(lead, bigint253, mod) leadChars = append(leadChars, byte(mod.Int64())+2) } lenLead := len(leadChars) if lenLead > 0 { for i := lenLead - 1; i >= 0; i-- { encoding = append(encoding, leadChars[i]) } } if left.Sign() == 1 { encoding = append(encoding, '\x01', byte(left.Int64())) } return encoding } value = value.Neg(value) if value.Cmp(cutoff) == -1 { encoding := []byte{'\x7f', '\xfe', '\xfe'} mod := big.NewInt(0) div, mod := value.DivMod(value, bigint255, mod) encoding[2] = 254 - byte(mod.Int64()) if div.Sign() == 1 { div, mod = div.DivMod(div, bigint255, mod) encoding[1] = 254 - byte(mod.Int64()) if div.Sign() == 1 { encoding[0] = 127 - byte(div.Int64()) } } return encoding } value = value.Sub(value, cutoff) encoding := []byte{'\x00'} left := big.NewInt(0) lead, left := value.DivMod(value, bigint254, left) var n int64 = 1 exp := big.NewInt(0) div := big.NewInt(0) for (div.Div(lead, exp.Exp(big.NewInt(253), big.NewInt(n), nil))).Sign() == 1 { n += 1 } encoding = append(encoding, 254-byte(n), '\x00') leadChars := make([]byte, 0) mod := big.NewInt(0) for { if lead.IsZero() { break } lead, mod = lead.DivMod(lead, bigint253, mod) leadChars = append(leadChars, byte(253-mod.Int64())) } lenLead := len(leadChars) if lenLead > 0 { for i := lenLead - 1; i >= 0; i-- { encoding = append(encoding, leadChars[i]) } } if lenLead > 1 { encoding = append(encoding, '\x00') } encoding = append(encoding, '\xfe') if left.Sign() == 1 { encoding = append(encoding, '\x01', 254-byte(left.Int64())) } else { encoding = append(encoding, '\xfe') } return encoding }