// bitwise contains bitwise operations for Uint instances. // This file includes functions to perform bitwise AND, OR, XOR, and NOT operations, as well as bit shifting. // These operations are crucial for manipulating individual bits within a 256-bit unsigned integer. package uint256 // Or sets z to the bitwise OR of x and y and returns z. func (z *Uint) Or(x, y *Uint) *Uint { z[0] = x[0] | y[0] z[1] = x[1] | y[1] z[2] = x[2] | y[2] z[3] = x[3] | y[3] return z } // And sets z to the bitwise AND of x and y and returns z. func (z *Uint) And(x, y *Uint) *Uint { z[0] = x[0] & y[0] z[1] = x[1] & y[1] z[2] = x[2] & y[2] z[3] = x[3] & y[3] return z } // Not sets z to the bitwise NOT of x and returns z. func (z *Uint) Not(x *Uint) *Uint { z[3], z[2], z[1], z[0] = ^x[3], ^x[2], ^x[1], ^x[0] return z } // AndNot sets z to x AND NOT y and returns z. func (z *Uint) AndNot(x, y *Uint) *Uint { z[0] = x[0] &^ y[0] z[1] = x[1] &^ y[1] z[2] = x[2] &^ y[2] z[3] = x[3] &^ y[3] return z } // Xor sets z to the bitwise XOR of x and y and returns z. func (z *Uint) Xor(x, y *Uint) *Uint { z[0] = x[0] ^ y[0] z[1] = x[1] ^ y[1] z[2] = x[2] ^ y[2] z[3] = x[3] ^ y[3] return z } // Lsh sets z to x left-shifted by n bits and returns z. // The result is truncated to 256 bits. If n >= 256, z is set to 0. func (z *Uint) Lsh(x *Uint, n uint) *Uint { if x.IsZero() { return z.Clear() } if n == 0 { return z.Set(x) } return z.lsh(x, n) } // lsh performs left shift without overflow checking func (z *Uint) lsh(x *Uint, n uint) *Uint { // n % 64 == 0 if n&0x3f == 0 { switch n { case 0: return z.Set(x) case 64: return z.lsh64(x) case 128: return z.lsh128(x) case 192: return z.lsh192(x) default: return z.Clear() } } var a, b uint64 // Big swaps first switch { case n > 192: z.lsh192(x) n -= 192 goto sh192 case n > 128: z.lsh128(x) n -= 128 goto sh128 case n > 64: z.lsh64(x) n -= 64 goto sh64 default: z.Set(x) } // remaining shifts a = z[0] >> (64 - n) z[0] = z[0] << n sh64: b = z[1] >> (64 - n) z[1] = (z[1] << n) | a sh128: a = z[2] >> (64 - n) z[2] = (z[2] << n) | b sh192: z[3] = (z[3] << n) | a return z } // Rsh sets z to x right-shifted by n bits and returns z. // If n >= 256, z is set to 0. func (z *Uint) Rsh(x *Uint, n uint) *Uint { // n % 64 == 0 if n&0x3f == 0 { switch n { case 0: return z.Set(x) case 64: return z.rsh64(x) case 128: return z.rsh128(x) case 192: return z.rsh192(x) default: return z.Clear() } } var a, b uint64 // Big swaps first switch { case n > 192: if n > 256 { return z.Clear() } z.rsh192(x) n -= 192 goto sh192 case n > 128: z.rsh128(x) n -= 128 goto sh128 case n > 64: z.rsh64(x) n -= 64 goto sh64 default: z.Set(x) } // remaining shifts a = z[3] << (64 - n) z[3] = z[3] >> n sh64: b = z[2] << (64 - n) z[2] = (z[2] >> n) | a sh128: a = z[1] << (64 - n) z[1] = (z[1] >> n) | b sh192: z[0] = (z[0] >> n) | a return z } // SRsh sets z to x arithmetically right-shifted by n bits and returns z. // It treats x as a signed two's complement integer. For negative values, // high-order bits are filled with 1s instead of 0s. If n >= 256 and x is negative, z is set to all 1s. func (z *Uint) SRsh(x *Uint, n uint) *Uint { // If the MSB is 0, SRsh is same as Rsh. if !x.isBitSet(255) { return z.Rsh(x, n) } if n%64 == 0 { switch n { case 0: return z.Set(x) case 64: return z.srsh64(x) case 128: return z.srsh128(x) case 192: return z.srsh192(x) default: return z.SetAllOne() } } var a uint64 = MAX_UINT64 << (64 - n%64) // Big swaps first switch { case n > 192: if n > 256 { return z.SetAllOne() } z.srsh192(x) n -= 192 goto sh192 case n > 128: z.srsh128(x) n -= 128 goto sh128 case n > 64: z.srsh64(x) n -= 64 goto sh64 default: z.Set(x) } // remaining shifts z[3], a = (z[3]>>n)|a, z[3]<<(64-n) sh64: z[2], a = (z[2]>>n)|a, z[2]<<(64-n) sh128: z[1], a = (z[1]>>n)|a, z[1]<<(64-n) sh192: z[0] = (z[0] >> n) | a return z } func (z *Uint) lsh64(x *Uint) *Uint { z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0 return z } func (z *Uint) lsh128(x *Uint) *Uint { z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0 return z } func (z *Uint) lsh192(x *Uint) *Uint { z[3], z[2], z[1], z[0] = x[0], 0, 0, 0 return z } func (z *Uint) rsh64(x *Uint) *Uint { z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1] return z } func (z *Uint) rsh128(x *Uint) *Uint { z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2] return z } func (z *Uint) rsh192(x *Uint) *Uint { z[3], z[2], z[1], z[0] = 0, 0, 0, x[3] return z } func (z *Uint) srsh64(x *Uint) *Uint { z[3], z[2], z[1], z[0] = MAX_UINT64, x[3], x[2], x[1] return z } func (z *Uint) srsh128(x *Uint) *Uint { z[3], z[2], z[1], z[0] = MAX_UINT64, MAX_UINT64, x[3], x[2] return z } func (z *Uint) srsh192(x *Uint) *Uint { z[3], z[2], z[1], z[0] = MAX_UINT64, MAX_UINT64, MAX_UINT64, x[3] return z }