Skip to content

Instantly share code, notes, and snippets.

@miguelmota
Created January 20, 2019 23:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miguelmota/5ea05395a021096aa395752d614d3972 to your computer and use it in GitHub Desktop.
Save miguelmota/5ea05395a021096aa395752d614d3972 to your computer and use it in GitHub Desktop.
Golang big number fromTwos bitwise operations example
const BN = require('bn.js')
const bn = new BN(Buffer.from('fb2e', 'hex'))
const width = bn.bitLength()
console.log(bn.fromTwos(width).toString()) // -1234
console.log(bn.notn(width).iaddn(1).ineg().toString()) // -1234
package main
import (
"fmt"
"math"
"math/big"
)
func main() {
x := []byte{0xfb, 0x2e}
i := new(big.Int)
i.SetBytes(x)
width := i.BitLen()
fmt.Println(fromTwos(i, width)) // -1234
}
func fromTwos(i *big.Int, width int) *big.Int {
a := inotn(i, width)
b := new(big.Int).Add(a, big.NewInt(1))
return new(big.Int).Neg(b)
}
func inotn(n *big.Int, width int) *big.Int {
words := n.Bits()
var bytesNeeded = int(math.Ceil(float64(width) / float64(26)))
var bitsLeft = width % 26
var length = n.BitLen()
// extend the buffer with leading zeroes
for length < bytesNeeded {
words[length] = 0
length = length + 1
}
if bitsLeft > 0 {
bytesNeeded--
}
var i int
// handle complete words
for i = 0; i < bytesNeeded; i++ {
words[i] = big.Word(^int(words[i]) & 0x3ffffff)
}
// handle the residue
if bitsLeft > 0 {
words[i] = big.Word(^int(words[i]) & (0x3ffffff >> (26 - uint(bitsLeft))))
}
ret := new(big.Int)
ret.SetBits(words)
return ret
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment