Search Apps Documentation Source Content File Folder Download Copy Actions Download

bitwise.gno

5.30 Kb ยท 302 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
  6import (
  7	"math/bits"
  8)
  9
 10// Or sets z to the bitwise OR of x and y and returns z.
 11func (z *Uint) Or(x, y *Uint) *Uint {
 12	z[0] = x[0] | y[0]
 13	z[1] = x[1] | y[1]
 14	z[2] = x[2] | y[2]
 15	z[3] = x[3] | y[3]
 16	return z
 17}
 18
 19// And sets z to the bitwise AND of x and y and returns z.
 20func (z *Uint) And(x, y *Uint) *Uint {
 21	z[0] = x[0] & y[0]
 22	z[1] = x[1] & y[1]
 23	z[2] = x[2] & y[2]
 24	z[3] = x[3] & y[3]
 25	return z
 26}
 27
 28// Not sets z to the bitwise NOT of x and returns z.
 29func (z *Uint) Not(x *Uint) *Uint {
 30	z[3], z[2], z[1], z[0] = ^x[3], ^x[2], ^x[1], ^x[0]
 31	return z
 32}
 33
 34// AndNot sets z to x AND NOT y and returns z.
 35func (z *Uint) AndNot(x, y *Uint) *Uint {
 36	z[0] = x[0] &^ y[0]
 37	z[1] = x[1] &^ y[1]
 38	z[2] = x[2] &^ y[2]
 39	z[3] = x[3] &^ y[3]
 40	return z
 41}
 42
 43// Xor sets z to the bitwise XOR of x and y and returns z.
 44func (z *Uint) Xor(x, y *Uint) *Uint {
 45	z[0] = x[0] ^ y[0]
 46	z[1] = x[1] ^ y[1]
 47	z[2] = x[2] ^ y[2]
 48	z[3] = x[3] ^ y[3]
 49	return z
 50}
 51
 52// Lsh sets z to x left-shifted by n bits and returns z.
 53// Panics if the shift would cause non-zero bits to overflow.
 54func (z *Uint) Lsh(x *Uint, n uint) *Uint {
 55	if x.IsZero() {
 56		return z.Clear()
 57	}
 58
 59	if n == 0 {
 60		return z.Set(x)
 61	}
 62
 63	// overflow check
 64	if n >= 256 {
 65		panic("Lsh: overflow")
 66	}
 67
 68	// headroom check
 69	top := -1
 70	for i := 3; i >= 0; i-- {
 71		if x[i] != 0 {
 72			top = i
 73			break
 74		}
 75	}
 76
 77	usedBits := bits.Len64(x[top])  // 1..64
 78	msbIndex := top*64 + (usedBits - 1) // 0..255
 79	headroom := 255 - msbIndex          // 0..255
 80	if n > uint(headroom) {
 81		panic("Lsh: overflow")
 82	}
 83
 84	// Perform the shift
 85	return z.lsh(x, n)
 86}
 87
 88// lsh performs left shift without overflow checking
 89func (z *Uint) lsh(x *Uint, n uint) *Uint {
 90	// n % 64 == 0
 91	if n&0x3f == 0 {
 92		switch n {
 93		case 0:
 94			return z.Set(x)
 95		case 64:
 96			return z.lsh64(x)
 97		case 128:
 98			return z.lsh128(x)
 99		case 192:
100			return z.lsh192(x)
101		default:
102			return z.Clear()
103		}
104	}
105	var a, b uint64
106	// Big swaps first
107	switch {
108	case n > 192:
109		z.lsh192(x)
110		n -= 192
111		goto sh192
112	case n > 128:
113		z.lsh128(x)
114		n -= 128
115		goto sh128
116	case n > 64:
117		z.lsh64(x)
118		n -= 64
119		goto sh64
120	default:
121		z.Set(x)
122	}
123
124	// remaining shifts
125	a = z[0] >> (64 - n)
126	z[0] = z[0] << n
127
128sh64:
129	b = z[1] >> (64 - n)
130	z[1] = (z[1] << n) | a
131
132sh128:
133	a = z[2] >> (64 - n)
134	z[2] = (z[2] << n) | b
135
136sh192:
137	z[3] = (z[3] << n) | a
138
139	return z
140}
141
142// Rsh sets z to x right-shifted by n bits and returns z.
143// If n >= 256, z is set to 0.
144func (z *Uint) Rsh(x *Uint, n uint) *Uint {
145	// n % 64 == 0
146	if n&0x3f == 0 {
147		switch n {
148		case 0:
149			return z.Set(x)
150		case 64:
151			return z.rsh64(x)
152		case 128:
153			return z.rsh128(x)
154		case 192:
155			return z.rsh192(x)
156		default:
157			return z.Clear()
158		}
159	}
160	var a, b uint64
161	// Big swaps first
162	switch {
163	case n > 192:
164		if n > 256 {
165			return z.Clear()
166		}
167		z.rsh192(x)
168		n -= 192
169		goto sh192
170	case n > 128:
171		z.rsh128(x)
172		n -= 128
173		goto sh128
174	case n > 64:
175		z.rsh64(x)
176		n -= 64
177		goto sh64
178	default:
179		z.Set(x)
180	}
181
182	// remaining shifts
183	a = z[3] << (64 - n)
184	z[3] = z[3] >> n
185
186sh64:
187	b = z[2] << (64 - n)
188	z[2] = (z[2] >> n) | a
189
190sh128:
191	a = z[1] << (64 - n)
192	z[1] = (z[1] >> n) | b
193
194sh192:
195	z[0] = (z[0] >> n) | a
196
197	return z
198}
199
200// SRsh sets z to x arithmetically right-shifted by n bits and returns z.
201// It treats x as a signed two's complement integer. For negative values,
202// high-order bits are filled with 1s instead of 0s. If n >= 256 and x is negative, z is set to all 1s.
203func (z *Uint) SRsh(x *Uint, n uint) *Uint {
204	// If the MSB is 0, SRsh is same as Rsh.
205	if !x.isBitSet(255) {
206		return z.Rsh(x, n)
207	}
208	if n%64 == 0 {
209		switch n {
210		case 0:
211			return z.Set(x)
212		case 64:
213			return z.srsh64(x)
214		case 128:
215			return z.srsh128(x)
216		case 192:
217			return z.srsh192(x)
218		default:
219			return z.SetAllOne()
220		}
221	}
222	var a uint64 = MAX_UINT64 << (64 - n%64)
223	// Big swaps first
224	switch {
225	case n > 192:
226		if n > 256 {
227			return z.SetAllOne()
228		}
229		z.srsh192(x)
230		n -= 192
231		goto sh192
232	case n > 128:
233		z.srsh128(x)
234		n -= 128
235		goto sh128
236	case n > 64:
237		z.srsh64(x)
238		n -= 64
239		goto sh64
240	default:
241		z.Set(x)
242	}
243
244	// remaining shifts
245	z[3], a = (z[3]>>n)|a, z[3]<<(64-n)
246
247sh64:
248	z[2], a = (z[2]>>n)|a, z[2]<<(64-n)
249
250sh128:
251	z[1], a = (z[1]>>n)|a, z[1]<<(64-n)
252
253sh192:
254	z[0] = (z[0] >> n) | a
255
256	return z
257}
258
259func (z *Uint) lsh64(x *Uint) *Uint {
260	z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0
261	return z
262}
263
264func (z *Uint) lsh128(x *Uint) *Uint {
265	z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0
266	return z
267}
268
269func (z *Uint) lsh192(x *Uint) *Uint {
270	z[3], z[2], z[1], z[0] = x[0], 0, 0, 0
271	return z
272}
273
274func (z *Uint) rsh64(x *Uint) *Uint {
275	z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1]
276	return z
277}
278
279func (z *Uint) rsh128(x *Uint) *Uint {
280	z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2]
281	return z
282}
283
284func (z *Uint) rsh192(x *Uint) *Uint {
285	z[3], z[2], z[1], z[0] = 0, 0, 0, x[3]
286	return z
287}
288
289func (z *Uint) srsh64(x *Uint) *Uint {
290	z[3], z[2], z[1], z[0] = MAX_UINT64, x[3], x[2], x[1]
291	return z
292}
293
294func (z *Uint) srsh128(x *Uint) *Uint {
295	z[3], z[2], z[1], z[0] = MAX_UINT64, MAX_UINT64, x[3], x[2]
296	return z
297}
298
299func (z *Uint) srsh192(x *Uint) *Uint {
300	z[3], z[2], z[1], z[0] = MAX_UINT64, MAX_UINT64, MAX_UINT64, x[3]
301	return z
302}