Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

bitwise.gno

6.47 Kb · 332 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.
  7//
  8// Parameters:
  9//   - x: First 256-bit operand.
 10//   - y: Second 256-bit operand.
 11//
 12// Returns:
 13//   - z: The 256-bit bitwise OR x | y, stored in the receiver.
 14func (z *Uint) Or(x, y *Uint) *Uint {
 15	z[0] = x[0] | y[0]
 16	z[1] = x[1] | y[1]
 17	z[2] = x[2] | y[2]
 18	z[3] = x[3] | y[3]
 19	return z
 20}
 21
 22// And sets z to the bitwise AND of x and y and returns z.
 23//
 24// Parameters:
 25//   - x: First 256-bit operand.
 26//   - y: Second 256-bit operand.
 27//
 28// Returns:
 29//   - z: The 256-bit bitwise AND x & y, stored in the receiver.
 30func (z *Uint) And(x, y *Uint) *Uint {
 31	z[0] = x[0] & y[0]
 32	z[1] = x[1] & y[1]
 33	z[2] = x[2] & y[2]
 34	z[3] = x[3] & y[3]
 35	return z
 36}
 37
 38// Not sets z to the bitwise complement of x and returns z.
 39//
 40// Parameters:
 41//   - x: 256-bit operand whose bits are complemented.
 42//
 43// Returns:
 44//   - z: The 256-bit bitwise complement ^x, stored in the receiver.
 45func (z *Uint) Not(x *Uint) *Uint {
 46	z[3], z[2], z[1], z[0] = ^x[3], ^x[2], ^x[1], ^x[0]
 47	return z
 48}
 49
 50// AndNot sets z to x AND NOT y and returns z.
 51//
 52// Parameters:
 53//   - x: First 256-bit operand.
 54//   - y: Operand whose bits are cleared from x.
 55//
 56// Returns:
 57//   - z: The 256-bit bit pattern x &^ y, stored in the receiver.
 58func (z *Uint) AndNot(x, y *Uint) *Uint {
 59	z[0] = x[0] &^ y[0]
 60	z[1] = x[1] &^ y[1]
 61	z[2] = x[2] &^ y[2]
 62	z[3] = x[3] &^ y[3]
 63	return z
 64}
 65
 66// Xor sets z to the bitwise exclusive OR of x and y and returns z.
 67//
 68// Parameters:
 69//   - x: First 256-bit operand.
 70//   - y: Second 256-bit operand.
 71//
 72// Returns:
 73//   - z: The 256-bit bitwise exclusive OR x ^ y, stored in the receiver.
 74func (z *Uint) Xor(x, y *Uint) *Uint {
 75	z[0] = x[0] ^ y[0]
 76	z[1] = x[1] ^ y[1]
 77	z[2] = x[2] ^ y[2]
 78	z[3] = x[3] ^ y[3]
 79	return z
 80}
 81
 82// Lsh sets z to x left-shifted by n bits and returns z.
 83// Bits shifted beyond the 256-bit width are discarded; n >= 256 produces zero.
 84//
 85// Parameters:
 86//   - x: 256-bit operand to shift.
 87//   - n: Number of bit positions to shift left.
 88//
 89// Returns:
 90//   - z: The low 256 bits of x << n, stored in the receiver.
 91func (z *Uint) Lsh(x *Uint, n uint) *Uint {
 92	if x.IsZero() {
 93		return z.Clear()
 94	}
 95
 96	if n == 0 {
 97		return z.Set(x)
 98	}
 99
100	return z.lsh(x, n)
101}
102
103// lsh performs left shift without overflow checking
104func (z *Uint) lsh(x *Uint, n uint) *Uint {
105	// n % 64 == 0
106	if n&0x3f == 0 {
107		switch n {
108		case 0:
109			return z.Set(x)
110		case 64:
111			return z.lsh64(x)
112		case 128:
113			return z.lsh128(x)
114		case 192:
115			return z.lsh192(x)
116		default:
117			return z.Clear()
118		}
119	}
120	var a, b uint64
121	// Big swaps first
122	switch {
123	case n > 192:
124		z.lsh192(x)
125		n -= 192
126		goto sh192
127	case n > 128:
128		z.lsh128(x)
129		n -= 128
130		goto sh128
131	case n > 64:
132		z.lsh64(x)
133		n -= 64
134		goto sh64
135	default:
136		z.Set(x)
137	}
138
139	// remaining shifts
140	a = z[0] >> (64 - n)
141	z[0] = z[0] << n
142
143sh64:
144	b = z[1] >> (64 - n)
145	z[1] = (z[1] << n) | a
146
147sh128:
148	a = z[2] >> (64 - n)
149	z[2] = (z[2] << n) | b
150
151sh192:
152	z[3] = (z[3] << n) | a
153
154	return z
155}
156
157// Rsh sets z to x logically right-shifted by n bits and returns z.
158// Zero bits are shifted in from the left, and n >= 256 produces zero.
159//
160// Parameters:
161//   - x: 256-bit operand to shift.
162//   - n: Number of bit positions to shift right.
163//
164// Returns:
165//   - z: The 256-bit logical right shift x >> n, stored in the receiver.
166func (z *Uint) Rsh(x *Uint, n uint) *Uint {
167	// n % 64 == 0
168	if n&0x3f == 0 {
169		switch n {
170		case 0:
171			return z.Set(x)
172		case 64:
173			return z.rsh64(x)
174		case 128:
175			return z.rsh128(x)
176		case 192:
177			return z.rsh192(x)
178		default:
179			return z.Clear()
180		}
181	}
182	var a, b uint64
183	// Big swaps first
184	switch {
185	case n > 192:
186		if n > 256 {
187			return z.Clear()
188		}
189		z.rsh192(x)
190		n -= 192
191		goto sh192
192	case n > 128:
193		z.rsh128(x)
194		n -= 128
195		goto sh128
196	case n > 64:
197		z.rsh64(x)
198		n -= 64
199		goto sh64
200	default:
201		z.Set(x)
202	}
203
204	// remaining shifts
205	a = z[3] << (64 - n)
206	z[3] = z[3] >> n
207
208sh64:
209	b = z[2] << (64 - n)
210	z[2] = (z[2] >> n) | a
211
212sh128:
213	a = z[1] << (64 - n)
214	z[1] = (z[1] >> n) | b
215
216sh192:
217	z[0] = (z[0] >> n) | a
218
219	return z
220}
221
222// SRsh sets z to x arithmetically right-shifted by n bits and returns z.
223// The top bit is treated as a sign bit: negative patterns receive one-fill,
224// while non-negative patterns use the logical right shift.
225//
226// Parameters:
227//   - x: 256-bit two's-complement bit pattern to shift.
228//   - n: Number of bit positions to shift right.
229//
230// Returns:
231//   - z: The arithmetic right shift of x, stored in the receiver; n >= 256
232//     yields all ones for a negative x and zero otherwise.
233func (z *Uint) SRsh(x *Uint, n uint) *Uint {
234	// If the MSB is 0, SRsh is same as Rsh.
235	if !x.isBitSet(255) {
236		return z.Rsh(x, n)
237	}
238	if n%64 == 0 {
239		switch n {
240		case 0:
241			return z.Set(x)
242		case 64:
243			return z.srsh64(x)
244		case 128:
245			return z.srsh128(x)
246		case 192:
247			return z.srsh192(x)
248		default:
249			return z.SetAllOne()
250		}
251	}
252	var a uint64 = 18446744073709551615 << (64 - n%64)
253	// Big swaps first
254	switch {
255	case n > 192:
256		if n > 256 {
257			return z.SetAllOne()
258		}
259		z.srsh192(x)
260		n -= 192
261		goto sh192
262	case n > 128:
263		z.srsh128(x)
264		n -= 128
265		goto sh128
266	case n > 64:
267		z.srsh64(x)
268		n -= 64
269		goto sh64
270	default:
271		z.Set(x)
272	}
273
274	// remaining shifts
275	z[3], a = (z[3]>>n)|a, z[3]<<(64-n)
276
277sh64:
278	z[2], a = (z[2]>>n)|a, z[2]<<(64-n)
279
280sh128:
281	z[1], a = (z[1]>>n)|a, z[1]<<(64-n)
282
283sh192:
284	z[0] = (z[0] >> n) | a
285
286	return z
287}
288
289func (z *Uint) lsh64(x *Uint) *Uint {
290	z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0
291	return z
292}
293
294func (z *Uint) lsh128(x *Uint) *Uint {
295	z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0
296	return z
297}
298
299func (z *Uint) lsh192(x *Uint) *Uint {
300	z[3], z[2], z[1], z[0] = x[0], 0, 0, 0
301	return z
302}
303
304func (z *Uint) rsh64(x *Uint) *Uint {
305	z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1]
306	return z
307}
308
309func (z *Uint) rsh128(x *Uint) *Uint {
310	z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2]
311	return z
312}
313
314func (z *Uint) rsh192(x *Uint) *Uint {
315	z[3], z[2], z[1], z[0] = 0, 0, 0, x[3]
316	return z
317}
318
319func (z *Uint) srsh64(x *Uint) *Uint {
320	z[3], z[2], z[1], z[0] = 18446744073709551615, x[3], x[2], x[1]
321	return z
322}
323
324func (z *Uint) srsh128(x *Uint) *Uint {
325	z[3], z[2], z[1], z[0] = 18446744073709551615, 18446744073709551615, x[3], x[2]
326	return z
327}
328
329func (z *Uint) srsh192(x *Uint) *Uint {
330	z[3], z[2], z[1], z[0] = 18446744073709551615, 18446744073709551615, 18446744073709551615, x[3]
331	return z
332}