github.com/mavryk-network/mvgo@v1.19.9/mavryk/zarith.go (about)

     1  // Copyright (c) 2020-2021 Blockwatch Data Inc.
     2  // Author: alex@blockwatch.cc
     3  
     4  // little-endian zarith encoding
     5  // https://github.com/ocaml/Zarith
     6  
     7  package mavryk
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/binary"
    12  	"fmt"
    13  	"io"
    14  	"math"
    15  	"math/big"
    16  	"strconv"
    17  	"strings"
    18  	"sync"
    19  )
    20  
    21  type Bool byte
    22  
    23  const (
    24  	False Bool = 0x00
    25  	True  Bool = 0xff
    26  )
    27  
    28  func (b Bool) EncodeBuffer(buf *bytes.Buffer) error {
    29  	buf.WriteByte(byte(b))
    30  	return nil
    31  }
    32  
    33  func (b *Bool) DecodeBuffer(buf *bytes.Buffer) error {
    34  	if buf.Len() < 1 {
    35  		return io.ErrShortBuffer
    36  	}
    37  	if buf.Next(1)[0] == 0xff {
    38  		*b = True
    39  	} else {
    40  		*b = False
    41  	}
    42  	return nil
    43  }
    44  
    45  // A variable length sequence of bytes, encoding a Zarith number.
    46  // Each byte has a running unary size bit: the most significant bit
    47  // of each byte tells if this is the last byte in the sequence (0)
    48  // or if there is more to read (1). The second most significant bit
    49  // of the first byte is reserved for the sign (positive if zero).
    50  // Size and sign bits ignored, data is then the binary representation
    51  // of the absolute value of the number in little endian order.
    52  type Z big.Int
    53  
    54  var Zero = NewZ(0)
    55  
    56  func NewZ(i int64) Z {
    57  	var z Z
    58  	z.SetInt64(i)
    59  	return z
    60  }
    61  
    62  func NewBigZ(b *big.Int) Z {
    63  	var z Z
    64  	z.SetBig(b)
    65  	return z
    66  }
    67  
    68  func (z Z) Big() *big.Int {
    69  	return (*big.Int)(&z)
    70  }
    71  
    72  func (z Z) Equal(x Z) bool {
    73  	return z.Big().Cmp(x.Big()) == 0
    74  }
    75  
    76  func (z Z) IsZero() bool {
    77  	return len((*big.Int)(&z).Bits()) == 0
    78  }
    79  
    80  func (z Z) Cmp(b Z) int {
    81  	return (*big.Int)(&z).Cmp((*big.Int)(&b))
    82  }
    83  
    84  func (z Z) IsLess(b Z) bool {
    85  	return z.Cmp(b) < 0
    86  }
    87  
    88  func (z Z) IsLessEqual(b Z) bool {
    89  	return z.Cmp(b) <= 0
    90  }
    91  
    92  func (z Z) Int64() int64 {
    93  	return (*big.Int)(&z).Int64()
    94  }
    95  
    96  func (z *Z) SetBig(b *big.Int) *Z {
    97  	(*big.Int)(z).Set(b)
    98  	return z
    99  }
   100  
   101  func (z *Z) SetInt64(i int64) *Z {
   102  	(*big.Int)(z).SetInt64(i)
   103  	return z
   104  }
   105  
   106  func (z Z) Clone() Z {
   107  	var x Z
   108  	x.SetBig(z.Big())
   109  	return x
   110  }
   111  
   112  func (z *Z) UnmarshalBinary(data []byte) error {
   113  	return z.DecodeBuffer(bytes.NewBuffer(data))
   114  }
   115  
   116  func (z *Z) DecodeBuffer(buf *bytes.Buffer) error {
   117  	tmp := make([]byte, 16)
   118  	var (
   119  		b   byte
   120  		err error
   121  	)
   122  	// read bits [0,6)
   123  	if b, err = buf.ReadByte(); err != nil {
   124  		return io.ErrShortBuffer
   125  	}
   126  	sign := b&0x40 > 0
   127  	tmp[0] = b & 0x3f
   128  	// read bits [6,62)
   129  	for i := 1; i < 9; i++ {
   130  		if b < 0x80 {
   131  			break
   132  		}
   133  		if b, err = buf.ReadByte(); err != nil {
   134  			return io.ErrShortBuffer
   135  		}
   136  		tmp[i] = b & 0x7f
   137  	}
   138  
   139  	w := int64(tmp[0]) | int64(tmp[1])<<6 | int64(tmp[2])<<13 | int64(tmp[3])<<20 | int64(tmp[4])<<27 |
   140  		int64(tmp[5])<<34 | int64(tmp[6])<<41 | int64(tmp[7])<<48 | int64(tmp[8])<<55
   141  
   142  	if b < 0x80 {
   143  		z.SetInt64(w)
   144  		if sign {
   145  			(*big.Int)(z).Neg((*big.Int)(z))
   146  		}
   147  		return nil
   148  	}
   149  
   150  	binary.BigEndian.PutUint64(tmp[0:8], 0)
   151  	tmp[8] = 0
   152  
   153  	// read bits [62,125)
   154  	for i := 0; i < 9; i++ {
   155  		if b < 0x80 {
   156  			break
   157  		}
   158  		if b, err = buf.ReadByte(); err != nil {
   159  			return io.ErrShortBuffer
   160  		}
   161  		tmp[i] = b & 0x7f
   162  	}
   163  
   164  	w |= int64(tmp[0]) << 62
   165  	w2 := int64(tmp[0])>>2 | int64(tmp[1])<<5 | int64(tmp[2])<<12 | int64(tmp[3])<<19 | int64(tmp[4])<<26 |
   166  		int64(tmp[5])<<33 | int64(tmp[6])<<40 | int64(tmp[7])<<47 | int64(tmp[8])<<54
   167  
   168  	binary.BigEndian.PutUint64(tmp[0:8], uint64(w2))
   169  	binary.BigEndian.PutUint64(tmp[8:16], uint64(w))
   170  	x := (*big.Int)(z).SetBytes(tmp[0:16])
   171  
   172  	if b < 0x80 {
   173  		if sign {
   174  			x.Neg(x)
   175  		}
   176  		return nil
   177  	}
   178  
   179  	var s uint = 125
   180  	y := bigIntPool.Get().(*big.Int)
   181  
   182  	// read bits >=125
   183  	for b >= 0x80 {
   184  		binary.BigEndian.PutUint64(tmp[0:8], 0)
   185  		tmp[8] = 0
   186  		for i := 0; i < 9; i++ {
   187  			if b < 0x80 {
   188  				break
   189  			}
   190  			if b, err = buf.ReadByte(); err != nil {
   191  				bigIntPool.Put(y)
   192  				return io.ErrShortBuffer
   193  			}
   194  			tmp[i] = b & 0x7f
   195  		}
   196  
   197  		w := int64(tmp[0]) | int64(tmp[1])<<7 | int64(tmp[2])<<14 | int64(tmp[3])<<21 | int64(tmp[4])<<28 |
   198  			int64(tmp[5])<<35 | int64(tmp[6])<<42 | int64(tmp[7])<<49 | int64(tmp[8])<<56
   199  
   200  		y.SetInt64(w)
   201  
   202  		x = x.Or(x, y.Lsh(y, s))
   203  		s += 63
   204  	}
   205  
   206  	bigIntPool.Put(y)
   207  
   208  	if sign {
   209  		x.Neg(x)
   210  	}
   211  	return nil
   212  }
   213  
   214  func (z Z) MarshalBinary() ([]byte, error) {
   215  	buf := bytes.NewBuffer(nil)
   216  	if err := z.EncodeBuffer(buf); err != nil {
   217  		return nil, err
   218  	}
   219  	return buf.Bytes(), nil
   220  }
   221  
   222  func (z *Z) EncodeBuffer(buf *bytes.Buffer) error {
   223  	xi := bigIntPool.Get()
   224  	x := xi.(*big.Int).Set((*big.Int)(z))
   225  	yi := bigIntPool.Get()
   226  	y := yi.(*big.Int).SetInt64(0)
   227  	var sign byte
   228  	if x.Sign() < 0 {
   229  		sign = 0x40
   230  		x.Neg(x)
   231  	}
   232  	if x.IsInt64() && x.Int64() < 0x40 {
   233  		buf.WriteByte(byte(x.Int64()) | sign)
   234  		bigIntPool.Put(xi)
   235  		bigIntPool.Put(yi)
   236  		return nil
   237  	} else {
   238  		buf.WriteByte(byte(y.And(x, mask3f).Int64()) | 0x80 | sign)
   239  		x.Rsh(x, 6)
   240  	}
   241  
   242  	for !x.IsInt64() || x.Int64() >= 0x80 {
   243  		buf.WriteByte(byte(y.And(x, mask7f).Int64()) | 0x80)
   244  		x.Rsh(x, 7)
   245  	}
   246  	buf.WriteByte(byte(x.Int64()))
   247  	bigIntPool.Put(xi)
   248  	bigIntPool.Put(yi)
   249  	return nil
   250  }
   251  
   252  func ParseZ(s string) (Z, error) {
   253  	var z Z
   254  	err := (*big.Int)(&z).UnmarshalText([]byte(s))
   255  	return z, err
   256  }
   257  
   258  func MustParseZ(s string) Z {
   259  	z, err := ParseZ(s)
   260  	if err != nil {
   261  		panic(err)
   262  	}
   263  	return z
   264  }
   265  
   266  // Set implements the flags.Value interface for use in command line argument parsing.
   267  func (z *Z) Set(val string) (err error) {
   268  	*z, err = ParseZ(val)
   269  	return
   270  }
   271  
   272  func (z Z) MarshalText() ([]byte, error) {
   273  	return (*big.Int)(&z).MarshalText()
   274  }
   275  
   276  func (z *Z) UnmarshalText(d []byte) error {
   277  	return (*big.Int)(z).UnmarshalText(d)
   278  }
   279  
   280  func (z Z) String() string {
   281  	return (*big.Int)(&z).Text(10)
   282  }
   283  
   284  func (z Z) Bytes() []byte {
   285  	buf, _ := z.MarshalBinary()
   286  	return buf
   287  }
   288  
   289  func (z Z) Decimals(d int) string {
   290  	s := z.String()
   291  	if d <= 0 {
   292  		return s
   293  	}
   294  	var sig string
   295  	if z.IsNeg() {
   296  		sig = "-"
   297  		s = s[1:]
   298  	}
   299  	l := len(s)
   300  	if l <= d {
   301  		s = strings.Repeat("0", d-l+1) + s
   302  	}
   303  	l = len(s)
   304  	return sig + s[:l-d] + "." + s[l-d:]
   305  }
   306  
   307  func (z Z) Neg() Z {
   308  	var n Z
   309  	n.SetBig(new(big.Int).Neg(z.Big()))
   310  	return n
   311  }
   312  
   313  func (z Z) Add(y Z) Z {
   314  	var x Z
   315  	x.SetBig(new(big.Int).Add(z.Big(), y.Big()))
   316  	return x
   317  }
   318  
   319  func (z Z) Sub(y Z) Z {
   320  	var x Z
   321  	x.SetBig(new(big.Int).Sub(z.Big(), y.Big()))
   322  	return x
   323  }
   324  
   325  func (z Z) Mul(y Z) Z {
   326  	var x Z
   327  	x.SetBig(new(big.Int).Mul(z.Big(), y.Big()))
   328  	return x
   329  }
   330  
   331  func (z Z) Div(y Z) Z {
   332  	var x Z
   333  	if !y.IsZero() {
   334  		x.SetBig(new(big.Int).Div(z.Big(), y.Big()))
   335  	}
   336  	return x
   337  }
   338  
   339  func (z Z) CeilDiv(y Z) Z {
   340  	var x Z
   341  	if !y.IsZero() {
   342  		d, m := new(big.Int).DivMod(z.Big(), y.Big(), new(big.Int))
   343  		x.SetBig(d)
   344  		x = x.Add64(int64(m.Cmp(Zero.Big())))
   345  	}
   346  	return x
   347  }
   348  
   349  func (z Z) Add64(y int64) Z {
   350  	var x Z
   351  	x.SetBig(new(big.Int).Add(z.Big(), big.NewInt(y)))
   352  	return x
   353  }
   354  
   355  func (z Z) Sub64(y int64) Z {
   356  	var x Z
   357  	x.SetBig(new(big.Int).Sub(z.Big(), big.NewInt(y)))
   358  	return x
   359  }
   360  
   361  func (z Z) Mul64(y int64) Z {
   362  	var x Z
   363  	x.SetBig(new(big.Int).Mul(z.Big(), big.NewInt(y)))
   364  	return x
   365  }
   366  
   367  func (z Z) Div64(y int64) Z {
   368  	var x Z
   369  	if y != 0 {
   370  		x.SetBig(new(big.Int).Div(z.Big(), big.NewInt(y)))
   371  	}
   372  	return x
   373  }
   374  
   375  func (z Z) IsNeg() bool {
   376  	return z.Big().Sign() < 0
   377  }
   378  
   379  func (z Z) Scale(n int) Z {
   380  	var x Z
   381  	if n == 0 {
   382  		x.SetBig(z.Big())
   383  	} else {
   384  		if n < 0 {
   385  			factor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(-n)), nil)
   386  			x.SetBig(factor.Div(z.Big(), factor))
   387  		} else {
   388  			factor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(n)), nil)
   389  			x.SetBig(factor.Mul(z.Big(), factor))
   390  		}
   391  	}
   392  	return x
   393  }
   394  
   395  func (z Z) CeilScale(n int) Z {
   396  	var x Z
   397  	if n == 0 {
   398  		x.SetBig(z.Big())
   399  	} else {
   400  		if n < 0 {
   401  			factor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(-n)), nil)
   402  			f, m := factor.DivMod(z.Big(), factor, new(big.Int))
   403  			x.SetBig(f)
   404  			x = x.Add64(int64(m.Cmp(Zero.Big())))
   405  		} else {
   406  			factor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(n)), nil)
   407  			x.SetBig(factor.Mul(z.Big(), factor))
   408  		}
   409  	}
   410  	return x
   411  }
   412  
   413  func (z Z) Float64(dec int) float64 {
   414  	f64, _ := new(big.Float).SetInt(z.Big()).Float64()
   415  	switch {
   416  	case dec == 0:
   417  		return f64
   418  	case dec < 0:
   419  		factor := math.Pow10(-dec)
   420  		return f64 / factor
   421  	default:
   422  		factor := math.Pow10(dec)
   423  		return f64 * factor
   424  	}
   425  }
   426  
   427  func (z Z) Lsh(n uint) Z {
   428  	return NewBigZ(new(big.Int).Lsh(z.Big(), n))
   429  }
   430  
   431  func (z Z) Rsh(n uint) Z {
   432  	return NewBigZ(new(big.Int).Rsh(z.Big(), n))
   433  }
   434  
   435  func MaxZ(args ...Z) Z {
   436  	var m Z
   437  	for _, z := range args {
   438  		if m.Cmp(z) < 0 {
   439  			m = z
   440  		}
   441  	}
   442  	return m
   443  }
   444  
   445  func MinZ(args ...Z) Z {
   446  	switch len(args) {
   447  	case 0:
   448  		return Z{}
   449  	case 1:
   450  		return args[0]
   451  	default:
   452  		m := args[0]
   453  		for _, z := range args[1:] {
   454  			if m.Cmp(z) > 0 {
   455  				m = z
   456  			}
   457  		}
   458  		return m
   459  	}
   460  }
   461  
   462  var (
   463  	mask3f     = big.NewInt(0x3f)
   464  	mask7f     = big.NewInt(0x7f)
   465  	bigIntPool = &sync.Pool{
   466  		New: func() interface{} { return big.NewInt(0) },
   467  	}
   468  )
   469  
   470  // A variable length sequence of bytes, encoding a Zarith number.
   471  // Each byte has a running unary size bit: the most significant bit
   472  // of each byte tells is this is the last byte in the sequence (0)
   473  // or if there is more to read (1). Size bits ignored, data is then
   474  // the binary representation of the absolute value of the number in
   475  // little endian order.
   476  type N int64
   477  
   478  func NewN(i int64) N {
   479  	return N(i)
   480  }
   481  
   482  func (n N) Equal(x N) bool {
   483  	return n == x
   484  }
   485  
   486  func (n N) IsZero() bool {
   487  	return n == 0
   488  }
   489  
   490  func (n N) Int64() int64 {
   491  	return int64(n)
   492  }
   493  
   494  func (n *N) SetInt64(i int64) *N {
   495  	*n = N(i)
   496  	return n
   497  }
   498  
   499  func (n N) Clone() N {
   500  	return n
   501  }
   502  
   503  func (n *N) DecodeBuffer(buf *bytes.Buffer) error {
   504  	var (
   505  		x int64
   506  		s uint
   507  	)
   508  	for i := 0; ; i++ {
   509  		b := buf.Next(1)
   510  		if len(b) == 0 {
   511  			return io.ErrShortBuffer
   512  		}
   513  		if b[0] < 0x80 {
   514  			if i > 9 || i == 9 && b[0] > 1 {
   515  				return fmt.Errorf("tezos: numeric overflow")
   516  			}
   517  			x |= int64(b[0]) << s
   518  			break
   519  		}
   520  		x |= int64(b[0]&0x7f) << s
   521  		s += 7
   522  	}
   523  	*n = N(x)
   524  	return nil
   525  }
   526  
   527  func (n N) EncodeBuffer(buf *bytes.Buffer) error {
   528  	x := int64(n)
   529  	for x >= 0x80 {
   530  		buf.WriteByte(byte(x) | 0x80)
   531  		x >>= 7
   532  	}
   533  	buf.WriteByte(byte(x))
   534  	return nil
   535  }
   536  
   537  func (n *N) UnmarshalBinary(data []byte) error {
   538  	return n.DecodeBuffer(bytes.NewBuffer(data))
   539  }
   540  
   541  func (n N) MarshalBinary() ([]byte, error) {
   542  	buf := bytes.NewBuffer(nil)
   543  	if err := n.EncodeBuffer(buf); err != nil {
   544  		return nil, err
   545  	}
   546  	return buf.Bytes(), nil
   547  }
   548  
   549  func (n N) MarshalText() ([]byte, error) {
   550  	return []byte(strconv.FormatInt(int64(n), 10)), nil
   551  }
   552  
   553  func (n *N) UnmarshalText(d []byte) error {
   554  	i, err := strconv.ParseInt(string(d), 10, 64)
   555  	if err != nil {
   556  		return err
   557  	}
   558  	*n = N(i)
   559  	return nil
   560  }
   561  
   562  func (n N) String() string {
   563  	return strconv.FormatInt(int64(n), 10)
   564  }
   565  
   566  func (n N) Decimals(d int) string {
   567  	s := n.String()
   568  	if d <= 0 {
   569  		return s
   570  	}
   571  	l := len(s)
   572  	if l <= d {
   573  		s = strings.Repeat("0", d-l+1) + s
   574  	}
   575  	l = len(s)
   576  	return s[:l-d] + "." + s[l-d:]
   577  }
   578  
   579  func ParseN(s string) (N, error) {
   580  	i, err := strconv.ParseInt(s, 10, 64)
   581  	if err != nil {
   582  		return N(0), err
   583  	}
   584  	return N(i), nil
   585  }
   586  
   587  // Set implements the flags.Value interface for use in command line argument parsing.
   588  func (n *N) Set(val string) (err error) {
   589  	*n, err = ParseN(val)
   590  	return
   591  }