fixedbig.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package replaydetector
  2. import (
  3. "fmt"
  4. )
  5. // fixedBigInt is the fix-sized multi-word integer.
  6. type fixedBigInt struct {
  7. bits []uint64
  8. n uint
  9. msbMask uint64
  10. }
  11. // newFixedBigInt creates a new fix-sized multi-word int.
  12. func newFixedBigInt(n uint) *fixedBigInt {
  13. chunkSize := (n + 63) / 64
  14. if chunkSize == 0 {
  15. chunkSize = 1
  16. }
  17. return &fixedBigInt{
  18. bits: make([]uint64, chunkSize),
  19. n: n,
  20. msbMask: (1 << (64 - n%64)) - 1,
  21. }
  22. }
  23. // Lsh is the left shift operation.
  24. func (s *fixedBigInt) Lsh(n uint) {
  25. if n == 0 {
  26. return
  27. }
  28. nChunk := int(n / 64)
  29. nN := n % 64
  30. for i := len(s.bits) - 1; i >= 0; i-- {
  31. var carry uint64
  32. if i-nChunk >= 0 {
  33. carry = s.bits[i-nChunk] << nN
  34. if i-nChunk-1 >= 0 {
  35. carry |= s.bits[i-nChunk-1] >> (64 - nN)
  36. }
  37. }
  38. s.bits[i] = (s.bits[i] << n) | carry
  39. }
  40. s.bits[len(s.bits)-1] &= s.msbMask
  41. }
  42. // Bit returns i-th bit of the fixedBigInt.
  43. func (s *fixedBigInt) Bit(i uint) uint {
  44. if i >= s.n {
  45. return 0
  46. }
  47. chunk := i / 64
  48. pos := i % 64
  49. if s.bits[chunk]&(1<<pos) != 0 {
  50. return 1
  51. }
  52. return 0
  53. }
  54. // SetBit sets i-th bit to 1.
  55. func (s *fixedBigInt) SetBit(i uint) {
  56. if i >= s.n {
  57. return
  58. }
  59. chunk := i / 64
  60. pos := i % 64
  61. s.bits[chunk] |= 1 << pos
  62. }
  63. // String returns string representation of fixedBigInt.
  64. func (s *fixedBigInt) String() string {
  65. var out string
  66. for i := len(s.bits) - 1; i >= 0; i-- {
  67. out += fmt.Sprintf("%016X", s.bits[i])
  68. }
  69. return out
  70. }