bitwise.gno

4.98 Kb ยท 264 lines
  1// bitwise contains bitwise operations for Uint instances.
  2// This file includes functions to perform bitwise AND, OR, XOR, and NOT operations, as well as bit shifting.
  3// These operations are crucial for manipulating individual bits within a 256-bit unsigned integer.
  4package uint256
  5
  6// Or sets z = x | y and returns z.
  7func (z *Uint) Or(x, y *Uint) *Uint {
  8	z.arr[0] = x.arr[0] | y.arr[0]
  9	z.arr[1] = x.arr[1] | y.arr[1]
 10	z.arr[2] = x.arr[2] | y.arr[2]
 11	z.arr[3] = x.arr[3] | y.arr[3]
 12	return z
 13}
 14
 15// And sets z = x & y and returns z.
 16func (z *Uint) And(x, y *Uint) *Uint {
 17	z.arr[0] = x.arr[0] & y.arr[0]
 18	z.arr[1] = x.arr[1] & y.arr[1]
 19	z.arr[2] = x.arr[2] & y.arr[2]
 20	z.arr[3] = x.arr[3] & y.arr[3]
 21	return z
 22}
 23
 24// Not sets z = ^x and returns z.
 25func (z *Uint) Not(x *Uint) *Uint {
 26	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = ^x.arr[3], ^x.arr[2], ^x.arr[1], ^x.arr[0]
 27	return z
 28}
 29
 30// AndNot sets z = x &^ y and returns z.
 31func (z *Uint) AndNot(x, y *Uint) *Uint {
 32	z.arr[0] = x.arr[0] &^ y.arr[0]
 33	z.arr[1] = x.arr[1] &^ y.arr[1]
 34	z.arr[2] = x.arr[2] &^ y.arr[2]
 35	z.arr[3] = x.arr[3] &^ y.arr[3]
 36	return z
 37}
 38
 39// Xor sets z = x ^ y and returns z.
 40func (z *Uint) Xor(x, y *Uint) *Uint {
 41	z.arr[0] = x.arr[0] ^ y.arr[0]
 42	z.arr[1] = x.arr[1] ^ y.arr[1]
 43	z.arr[2] = x.arr[2] ^ y.arr[2]
 44	z.arr[3] = x.arr[3] ^ y.arr[3]
 45	return z
 46}
 47
 48// Lsh sets z = x << n and returns z.
 49func (z *Uint) Lsh(x *Uint, n uint) *Uint {
 50	// n % 64 == 0
 51	if n&0x3f == 0 {
 52		switch n {
 53		case 0:
 54			return z.Set(x)
 55		case 64:
 56			return z.lsh64(x)
 57		case 128:
 58			return z.lsh128(x)
 59		case 192:
 60			return z.lsh192(x)
 61		default:
 62			return z.Clear()
 63		}
 64	}
 65	var a, b uint64
 66	// Big swaps first
 67	switch {
 68	case n > 192:
 69		if n > 256 {
 70			return z.Clear()
 71		}
 72		z.lsh192(x)
 73		n -= 192
 74		goto sh192
 75	case n > 128:
 76		z.lsh128(x)
 77		n -= 128
 78		goto sh128
 79	case n > 64:
 80		z.lsh64(x)
 81		n -= 64
 82		goto sh64
 83	default:
 84		z.Set(x)
 85	}
 86
 87	// remaining shifts
 88	a = z.arr[0] >> (64 - n)
 89	z.arr[0] = z.arr[0] << n
 90
 91sh64:
 92	b = z.arr[1] >> (64 - n)
 93	z.arr[1] = (z.arr[1] << n) | a
 94
 95sh128:
 96	a = z.arr[2] >> (64 - n)
 97	z.arr[2] = (z.arr[2] << n) | b
 98
 99sh192:
100	z.arr[3] = (z.arr[3] << n) | a
101
102	return z
103}
104
105// Rsh sets z = x >> n and returns z.
106func (z *Uint) Rsh(x *Uint, n uint) *Uint {
107	// n % 64 == 0
108	if n&0x3f == 0 {
109		switch n {
110		case 0:
111			return z.Set(x)
112		case 64:
113			return z.rsh64(x)
114		case 128:
115			return z.rsh128(x)
116		case 192:
117			return z.rsh192(x)
118		default:
119			return z.Clear()
120		}
121	}
122	var a, b uint64
123	// Big swaps first
124	switch {
125	case n > 192:
126		if n > 256 {
127			return z.Clear()
128		}
129		z.rsh192(x)
130		n -= 192
131		goto sh192
132	case n > 128:
133		z.rsh128(x)
134		n -= 128
135		goto sh128
136	case n > 64:
137		z.rsh64(x)
138		n -= 64
139		goto sh64
140	default:
141		z.Set(x)
142	}
143
144	// remaining shifts
145	a = z.arr[3] << (64 - n)
146	z.arr[3] = z.arr[3] >> n
147
148sh64:
149	b = z.arr[2] << (64 - n)
150	z.arr[2] = (z.arr[2] >> n) | a
151
152sh128:
153	a = z.arr[1] << (64 - n)
154	z.arr[1] = (z.arr[1] >> n) | b
155
156sh192:
157	z.arr[0] = (z.arr[0] >> n) | a
158
159	return z
160}
161
162// SRsh (Signed/Arithmetic right shift)
163// considers z to be a signed integer, during right-shift
164// and sets z = x >> n and returns z.
165func (z *Uint) SRsh(x *Uint, n uint) *Uint {
166	// If the MSB is 0, SRsh is same as Rsh.
167	if !x.isBitSet(255) {
168		return z.Rsh(x, n)
169	}
170	if n%64 == 0 {
171		switch n {
172		case 0:
173			return z.Set(x)
174		case 64:
175			return z.srsh64(x)
176		case 128:
177			return z.srsh128(x)
178		case 192:
179			return z.srsh192(x)
180		default:
181			return z.SetAllOne()
182		}
183	}
184	var a uint64 = MaxUint64 << (64 - n%64)
185	// Big swaps first
186	switch {
187	case n > 192:
188		if n > 256 {
189			return z.SetAllOne()
190		}
191		z.srsh192(x)
192		n -= 192
193		goto sh192
194	case n > 128:
195		z.srsh128(x)
196		n -= 128
197		goto sh128
198	case n > 64:
199		z.srsh64(x)
200		n -= 64
201		goto sh64
202	default:
203		z.Set(x)
204	}
205
206	// remaining shifts
207	z.arr[3], a = (z.arr[3]>>n)|a, z.arr[3]<<(64-n)
208
209sh64:
210	z.arr[2], a = (z.arr[2]>>n)|a, z.arr[2]<<(64-n)
211
212sh128:
213	z.arr[1], a = (z.arr[1]>>n)|a, z.arr[1]<<(64-n)
214
215sh192:
216	z.arr[0] = (z.arr[0] >> n) | a
217
218	return z
219}
220
221func (z *Uint) lsh64(x *Uint) *Uint {
222	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = x.arr[2], x.arr[1], x.arr[0], 0
223	return z
224}
225
226func (z *Uint) lsh128(x *Uint) *Uint {
227	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = x.arr[1], x.arr[0], 0, 0
228	return z
229}
230
231func (z *Uint) lsh192(x *Uint) *Uint {
232	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = x.arr[0], 0, 0, 0
233	return z
234}
235
236func (z *Uint) rsh64(x *Uint) *Uint {
237	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, x.arr[3], x.arr[2], x.arr[1]
238	return z
239}
240
241func (z *Uint) rsh128(x *Uint) *Uint {
242	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, 0, x.arr[3], x.arr[2]
243	return z
244}
245
246func (z *Uint) rsh192(x *Uint) *Uint {
247	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = 0, 0, 0, x.arr[3]
248	return z
249}
250
251func (z *Uint) srsh64(x *Uint) *Uint {
252	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, x.arr[3], x.arr[2], x.arr[1]
253	return z
254}
255
256func (z *Uint) srsh128(x *Uint) *Uint {
257	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, MaxUint64, x.arr[3], x.arr[2]
258	return z
259}
260
261func (z *Uint) srsh192(x *Uint) *Uint {
262	z.arr[3], z.arr[2], z.arr[1], z.arr[0] = MaxUint64, MaxUint64, MaxUint64, x.arr[3]
263	return z
264}