-
Notifications
You must be signed in to change notification settings - Fork 0
/
uint256.go
156 lines (134 loc) · 3.5 KB
/
uint256.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package uint256
import (
"fmt"
"log"
"github.com/kg6zvp/go-intdian"
)
// length of a Key in uint64
const LENGTH = 4
// number of bytes in a uint64, for convenience
const STEP_SIZE = 8
// number of bytes in a Uint256
const BYTE_LENGTH = STEP_SIZE * LENGTH
type Uint256 [LENGTH]uint64
// Comparitors
// Equal checks equality between this Uint256 and another one
// params:
// b: Uint256 to compare against
// returns: bool
func (a *Uint256) Equal(b Uint256) bool {
comp := getComp()
it := getIt()
for i := getStart(); comp(i); i = it(i) {
if a[i] != b[i] {
return false
}
}
return true
}
// IsEmpty checks whether this Uint256 is empty
// returns: bool
func (a *Uint256) IsEmpty() bool {
return a.Equal(EmptyUint256())
}
// LessThan checks if the given Uint256 is less than this Uint256
// params:
// b: Uint256 to compare against
// returns: bool
func (a *Uint256) LessThan(b Uint256) bool {
if b.IsEmpty() { //if it's empty, we don't care to compare
return false
}
comp := getComp()
it := getIt()
for i := getStart(); comp(i); i = it(i) {
if a[i] < b[i] {
return true
} else if a[i] > b[i] {
return false
} // continue to a less significant digit if they are equal
}
return false
}
// GreaterThan checks if the given Uint256 is more than this Uint256
// params:
// b: Uint256 to compare against
// returns: bool
func (a *Uint256) GreaterThan(b Uint256) bool {
return !a.Equal(b) && !a.LessThan(b)
}
// Operations
// Xor calculates the xor of two Uint256's (no side-effects)
// params:
// b: Uint256 to compare against
// returns: Uint256 representing the difference
func (a *Uint256) Xor(b Uint256) Uint256 {
var output Uint256
output = Uint256{}
comp := getComp()
it := getIt()
for i := getStart(); comp(i); i = it(i) {
output[i] = a[i] ^ b[i]
}
return output
}
// Conversions
// ToBytes converts this Uint256 into a []byte
// returns: []byte
func (a *Uint256) ToBytes() []byte {
out := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
comp := getComp()
it := getIt()
for i := getStart(); comp(i); i = it(i) {
intdian.ByteOrder().PutUint64(out[i*STEP_SIZE:], a[i])
}
return out
}
// FACTORY METHODS
// FromBytes creates a Uint256 from a [32]byte
// params:
// data: []byte
// returns: Uint256
// Fatal error for incorrect data length
func FromBytes(data []byte) Uint256 {
if len(data) != BYTE_LENGTH {
log.Fatalf("Incorrect data length: %d", len(data))
}
return Uint256{
intdian.ByteOrder().Uint64(data[0:8]),
intdian.ByteOrder().Uint64(data[8:16]),
intdian.ByteOrder().Uint64(data[16:24]),
intdian.ByteOrder().Uint64(data[24:32]),
}
}
// Constructors
// EmptyUint256 returns an empty Uint256
// returns: Uint256
func EmptyUint256() Uint256 {
return Uint256{0, 0, 0, 0}
}
// New returns a Uint256 with ordered most to least significant digits as params
// params:
// num: ...uint64 most-to-least significant digit
// returns: Uint256
func New(num ...uint64) (Uint256, error) {
if len(num) > LENGTH {
return Uint256{}, fmt.Errorf("Wrong number of arguments given. Expected <=%d, got %d", LENGTH, len(num))
}
comp := getComp()
it := getIt()
v := EmptyUint256()
// https://imgur.com/gallery/0QmLNmx
for i, k := skipBy(it, getStart(), LENGTH-len(num)), 0; comp(i) && k < LENGTH; i, k = it(i), k+1 {
v[i] = num[k]
}
return v, nil
}
// NewUnsafe will return an Uint256 or panic if the input is invalid
func NewUnsafe(num ...uint64) Uint256 {
v, err := New(num...)
if err != nil {
panic(err)
}
return v
}