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 }