| package ipbits |
| |
| import ( |
| "encoding/binary" |
| "math/bits" |
| ) |
| |
| type uint128 struct{ hi, lo uint64 } |
| |
| func uint128From16(b [16]byte) uint128 { |
| return uint128{ |
| hi: binary.BigEndian.Uint64(b[:8]), |
| lo: binary.BigEndian.Uint64(b[8:]), |
| } |
| } |
| |
| func uint128From(x uint64) uint128 { |
| return uint128{lo: x} |
| } |
| |
| func (x uint128) add(y uint128) uint128 { |
| lo, carry := bits.Add64(x.lo, y.lo, 0) |
| hi, _ := bits.Add64(x.hi, y.hi, carry) |
| return uint128{hi: hi, lo: lo} |
| } |
| |
| func (x uint128) sub(y uint128) uint128 { |
| lo, carry := bits.Sub64(x.lo, y.lo, 0) |
| hi, _ := bits.Sub64(x.hi, y.hi, carry) |
| return uint128{hi: hi, lo: lo} |
| } |
| |
| func (x uint128) lsh(n uint) uint128 { |
| if n > 64 { |
| return uint128{hi: x.lo << (n - 64)} |
| } |
| return uint128{ |
| hi: x.hi<<n | x.lo>>(64-n), |
| lo: x.lo << n, |
| } |
| } |
| |
| func (x uint128) rsh(n uint) uint128 { |
| if n > 64 { |
| return uint128{lo: x.hi >> (n - 64)} |
| } |
| return uint128{ |
| hi: x.hi >> n, |
| lo: x.lo>>n | x.hi<<(64-n), |
| } |
| } |
| |
| func (x uint128) and(y uint128) uint128 { |
| return uint128{hi: x.hi & y.hi, lo: x.lo & y.lo} |
| } |
| |
| func (x uint128) not() uint128 { |
| return uint128{hi: ^x.hi, lo: ^x.lo} |
| } |
| |
| func (x uint128) fill16(a *[16]byte) { |
| binary.BigEndian.PutUint64(a[:8], x.hi) |
| binary.BigEndian.PutUint64(a[8:], x.lo) |
| } |
| |
| func (x uint128) uint64() uint64 { |
| return x.lo |
| } |