Search Apps Documentation Source Content File Folder Download Copy Actions Download

bitwise.gno

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