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  }