github.com/primecitizens/pcz/std@v0.2.1/builtin/int/int128.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2020 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 package stdint 9 10 import ( 11 "github.com/primecitizens/pcz/std/core/bits" 12 ) 13 14 type Int128 Uint128 15 16 // Uint128 represents a Uint128 using two uint64s. 17 // 18 // When the methods below mention a bit number, bit 0 is the most 19 // significant bit (in hi) and bit 127 is the lowest (lo&1). 20 // 21 // NOTE: Uint128 is kept as struct instead of array because array of size > 1 22 // doesn't go through SSA, see https://github.com/golang/go/issues/24416 23 type Uint128 struct { 24 hi uint64 25 lo uint64 26 } 27 28 func (u Uint128) Equals(o Uint128) bool { return u.hi == o.hi && u.lo == o.lo } 29 30 // IsZero reports whether u == 0. 31 // 32 // It's faster than u == (uint128{}) because the compiler (as of Go 33 // 1.15/1.16b1) doesn't do this trick and instead inserts a branch in 34 // its eq alg's generated code. 35 func (u Uint128) IsZero() bool { return u.hi|u.lo == 0 } 36 37 // AND returns the bitwise AND of u AND m (u&m). 38 func (u Uint128) AND(m Uint128) Uint128 { return Uint128{hi: u.hi & m.hi, lo: u.lo & m.lo} } 39 40 // XOR returns the bitwise XOR of u and m (u^m). 41 func (u Uint128) XOR(m Uint128) Uint128 { return Uint128{hi: u.hi ^ m.hi, lo: u.lo ^ m.lo} } 42 43 // OR returns the bitwise OR of u and m (u|m). 44 func (u Uint128) OR(m Uint128) Uint128 { return Uint128{hi: u.hi | m.hi, lo: u.lo | m.lo} } 45 46 // NOT returns the bitwise NOT of u. 47 func (u Uint128) NOT() Uint128 { return Uint128{hi: ^u.hi, lo: ^u.lo} } 48 49 // SubOne returns u - 1. 50 func (u Uint128) SubOne() Uint128 { 51 lo, borrow := bits.Sub64(u.lo, 1, 0) 52 return Uint128{hi: u.hi - borrow, lo: lo} 53 } 54 55 // AddOne returns u + 1. 56 func (u Uint128) AddOne() Uint128 { 57 lo, carry := bits.Add64(u.lo, 1, 0) 58 return Uint128{hi: u.hi + carry, lo: lo} 59 } 60 61 func (u Uint128) Add(n Uint128) Uint128 { 62 lo, carry := bits.Add64(u.lo, n.lo, 0) 63 hi, carry := bits.Add64(u.hi, u.lo, carry) 64 if carry != 0 { 65 // overflow? 66 } 67 return Uint128{hi: hi, lo: lo} 68 } 69 70 func (u Uint128) Sub64(n uint64) Uint128 { 71 lo, carry := bits.Sub64(u.lo, n, 0) 72 return Uint128{hi: u.hi + carry, lo: lo} 73 } 74 75 func (u Uint128) Add64(n uint64) Uint128 { 76 lo, carry := bits.Add64(u.lo, n, 0) 77 return Uint128{hi: u.hi + carry, lo: lo} 78 } 79 80 // bitsSetFrom returns a copy of u with the given bit 81 // and all subsequent ones set. 82 func (u Uint128) bitsSetFrom(bit uint8) Uint128 { 83 return u.OR(mask6(int(bit)).NOT()) 84 } 85 86 // bitsClearedFrom returns a copy of u with the given bit 87 // and all subsequent ones cleared. 88 func (u Uint128) bitsClearedFrom(bit uint8) Uint128 { 89 return u.AND(mask6(int(bit))) 90 } 91 92 // mask6 returns a uint128 bitmask with the topmost n bits of a 93 // 128-bit number. 94 func mask6(n int) Uint128 { 95 return Uint128{hi: ^(^uint64(0) >> n), lo: ^uint64(0) << (128 - n)} 96 }