init: v1.0.0

This commit is contained in:
yaole
2026-05-27 23:03:00 +08:00
commit 8d97f750eb
466 changed files with 80067 additions and 0 deletions
+957
View File
@@ -0,0 +1,957 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements signed multi-precision integers.
// +build gmp
package gmp
// FIXME could we use Go's allocator (gmp can use a custom allocator)
// instead of using runtime.SetFinalizer to manage memory?
/*
#cgo LDFLAGS: -lgmp
#include <gmp.h>
#include <stdlib.h>
// gmp 5.0.0+ changed the type of the 3rd argument to mp_bitcnt_t,
// so, to support older versions, we wrap these two functions.
void _mpz_mul_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
mpz_mul_2exp(a, b, n);
}
void _mpz_div_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
mpz_div_2exp(a, b, n);
}
unsigned int _mpz_tstbit(mpz_ptr a, unsigned long n) {
return mpz_tstbit(a, n);
}
void _mpz_clrbit(mpz_ptr a, unsigned long n) {
mpz_clrbit(a, n);
}
void _mpz_setbit(mpz_ptr a, unsigned long n) {
mpz_setbit(a, n);
}
// Macros made into functions
int _mpz_sgn(mpz_t op) {
return mpz_sgn(op);
}
*/
import "C"
import (
"errors"
"fmt"
"io"
"math/rand"
"runtime"
"strings"
"unicode"
"unsafe"
)
// Some definited Ints for internal use only
var (
_Int0 = NewInt(0)
_Int1 = NewInt(1)
_Int10 = NewInt(10)
)
// An Int represents a signed multi-precision integer.
// The zero value for an Int represents the value 0.
type Int struct {
i C.mpz_t
init bool
}
// Finalizer - release the memory allocated to the mpz
func intFinalize(z *Int) {
if z.init {
runtime.SetFinalizer(z, nil)
C.mpz_clear(&z.i[0])
z.init = false
}
}
// Int promises that the zero value is a 0, but in gmp
// the zero value is a crash. To bridge the gap, the
// init bool says whether this is a valid gmp value.
// doinit initializes z.i if it needs it.
func (z *Int) doinit() {
if z.init {
return
}
z.init = true
C.mpz_init(&z.i[0])
runtime.SetFinalizer(z, intFinalize)
}
// Clear the allocated space used by the number
//
// This normally happens on a runtime.SetFinalizer call, but if you
// want immediate deallocation you can call it.
//
// NB This is not part of big.Int
func (z *Int) Clear() {
intFinalize(z)
}
// Sign returns:
//
// -1 if x < 0
// 0 if x == 0
// +1 if x > 0
//
func (z *Int) Sign() int {
z.doinit()
return int(C._mpz_sgn(&z.i[0]))
}
// SetInt64 sets z to x and returns z.
func (z *Int) SetInt64(x int64) *Int {
z.doinit()
// Test for truncation
y := C.long(x)
if int64(y) == x {
C.mpz_set_si(&z.i[0], y)
} else {
negative := false
if x < 0 {
x = -x
negative = true
}
C.mpz_import(&z.i[0], 1, 0, 8, 0, 0, unsafe.Pointer(&x))
if negative {
C.mpz_neg(&z.i[0], &z.i[0])
}
}
return z
}
// SetUint64 sets z to x and returns z.
func (z *Int) SetUint64(x uint64) *Int {
z.doinit()
// Test for truncation
y := C.ulong(x)
if uint64(y) == x {
C.mpz_set_ui(&z.i[0], y)
} else {
C.mpz_import(&z.i[0], 1, 0, 8, 0, 0, unsafe.Pointer(&x))
}
return z
}
// NewInt allocates and returns a new Int set to x.
func NewInt(x int64) *Int {
return new(Int).SetInt64(x)
}
// Set sets z to x and returns z.
func (z *Int) Set(x *Int) *Int {
z.doinit()
C.mpz_set(&z.i[0], &x.i[0])
return z
}
// Bits provides raw (unchecked but fast) access to x by returning its
// absolute value as a little-endian Word slice. The result and x share
// the same underlying array.
// Bits is intended to support implementation of missing low-level Int
// functionality outside this package; it should be avoided otherwise.
// func (z *Int) Bits() []Word {
// // FIXME not implemented
// return nil
// }
// SetBits provides raw (unchecked but fast) access to z by setting its
// value to abs, interpreted as a little-endian Word slice, and returning
// z. The result and abs share the same underlying array.
// SetBits is intended to support implementation of missing low-level Int
// functionality outside this package; it should be avoided otherwise.
// func (z *Int) SetBits(abs []Word) *Int {
// // FIXME not implemented
// return nil
// }
// Abs sets z to |x| (the absolute value of x) and returns z.
func (z *Int) Abs(x *Int) *Int {
x.doinit()
z.doinit()
C.mpz_abs(&z.i[0], &x.i[0])
return z
}
// Neg sets z to -x and returns z.
func (z *Int) Neg(x *Int) *Int {
x.doinit()
z.doinit()
C.mpz_neg(&z.i[0], &x.i[0])
return z
}
// Add sets z to the sum x+y and returns z.
func (z *Int) Add(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
C.mpz_add(&z.i[0], &x.i[0], &y.i[0])
return z
}
// Sub sets z to the difference x-y and returns z.
func (z *Int) Sub(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
C.mpz_sub(&z.i[0], &x.i[0], &y.i[0])
return z
}
// Mul sets z to the product x*y and returns z.
func (z *Int) Mul(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
C.mpz_mul(&z.i[0], &x.i[0], &y.i[0])
return z
}
// MulRange sets z to the product of all integers
// in the range [a, b] inclusively and returns z.
// If a > b (empty range), the result is 1.
func (z *Int) MulRange(a, b int64) *Int {
switch {
case a > b:
return z.SetInt64(1) // empty range
case a <= 0 && b >= 0:
return z.SetInt64(0) // range includes 0
}
// a <= b && (b < 0 || a > 0)
// Can use gmp factorial routine if a = 1 and b >= 1
if a == 1 && b >= 1 {
C.mpz_fac_ui(&z.i[0], C.ulong(b))
} else {
// Slow
z.SetInt64(a)
for i := a + 1; i <= b; i++ {
C.mpz_mul_si(&z.i[0], &z.i[0], C.long(i))
}
}
return z
}
// Binomial sets z to the binomial coefficient of (n, k) and returns z.
func (z *Int) Binomial(n, k int64) *Int {
var a, b Int
a.MulRange(n-k+1, n)
b.MulRange(1, k)
return z.Quo(&a, &b)
}
// Quo sets z to the quotient x/y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
// Quo implements truncated division (like Go); see QuoRem for more details.
func (z *Int) Quo(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
C.mpz_tdiv_q(&z.i[0], &x.i[0], &y.i[0])
return z
}
// Rem sets z to the remainder x%y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
// Rem implements truncated modulus (like Go); see QuoRem for more details.
func (z *Int) Rem(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
C.mpz_tdiv_r(&z.i[0], &x.i[0], &y.i[0])
return z
}
// QuoRem sets z to the quotient x/y and r to the remainder x%y
// and returns the pair (z, r) for y != 0.
// If y == 0, a division-by-zero run-time panic occurs.
//
// QuoRem implements T-division and modulus (like Go):
//
// q = x/y with the result truncated to zero
// r = x - y*q
//
// (See Daan Leijen, ``Division and Modulus for Computer Scientists''.)
// See DivMod for Euclidean division and modulus (unlike Go).
//
func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) {
x.doinit()
y.doinit()
r.doinit()
z.doinit()
C.mpz_tdiv_qr(&z.i[0], &r.i[0], &x.i[0], &y.i[0])
return z, r
}
// Div sets z to the quotient x/y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
// Div implements Euclidean division (unlike Go); see DivMod for more details.
func (z *Int) Div(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
switch y.Sign() {
case 1:
C.mpz_fdiv_q(&z.i[0], &x.i[0], &y.i[0])
case -1:
C.mpz_cdiv_q(&z.i[0], &x.i[0], &y.i[0])
case 0:
panic("Division by zero")
}
return z
}
// Mod sets z to the modulus x%y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
// Mod implements Euclidean modulus (unlike Go); see DivMod for more details.
func (z *Int) Mod(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
switch y.Sign() {
case 1:
C.mpz_fdiv_r(&z.i[0], &x.i[0], &y.i[0])
case -1:
C.mpz_cdiv_r(&z.i[0], &x.i[0], &y.i[0])
case 0:
panic("Division by zero")
}
return z
}
// DivMod sets z to the quotient x div y and m to the modulus x mod y
// and returns the pair (z, m) for y != 0.
// If y == 0, a division-by-zero run-time panic occurs.
//
// DivMod implements Euclidean division and modulus (unlike Go):
//
// q = x div y such that
// m = x - y*q with 0 <= m < |q|
//
// (See Raymond T. Boute, ``The Euclidean definition of the functions
// div and mod''. ACM Transactions on Programming Languages and
// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992.
// ACM press.)
// See QuoRem for T-division and modulus (like Go).
//
func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) {
x.doinit()
y.doinit()
m.doinit()
z.doinit()
switch y.Sign() {
case 1:
C.mpz_fdiv_qr(&z.i[0], &m.i[0], &x.i[0], &y.i[0])
case -1:
C.mpz_cdiv_qr(&z.i[0], &m.i[0], &x.i[0], &y.i[0])
case 0:
panic("Division by zero")
}
return z, m
}
// Cmp compares z and y and returns:
//
// -1 if z < y
// 0 if z == y
// +1 if z > y
//
func (z *Int) Cmp(y *Int) (r int) {
z.doinit()
y.doinit()
r = int(C.mpz_cmp(&z.i[0], &y.i[0]))
if r < 0 {
r = -1
} else if r > 0 {
r = 1
}
return
}
// string returns z in the base given
func (z *Int) string(base int) string {
if z == nil {
return "<nil>"
}
z.doinit()
p := C.mpz_get_str(nil, C.int(base), &z.i[0])
s := C.GoString(p)
C.free(unsafe.Pointer(p))
return s
}
// String returns the decimal representation of z.
func (z *Int) String() string {
return z.string(10)
}
// Convert rune into base
//
// Note gmp says -ve bases make upper case
func baseForRune(ch rune) int {
switch ch {
case 'b':
return 2
case 'o':
return 8
case 'd', 's', 'v':
return 10
case 'x':
return 16
case 'X':
return -16
}
return 0 // unknown format
}
// write count copies of text to s
func writeMultiple(s fmt.State, text string, count int) {
if len(text) > 0 {
b := []byte(text)
for ; count > 0; count-- {
_, _ = s.Write(b)
}
}
}
// Format is a support routine for fmt.Formatter. It accepts
// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
// Also supported are the full suite of package fmt's format
// verbs for integral types, including '+', '-', and ' '
// for sign control, '#' for leading zero in octal and for
// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
// respectively, specification of minimum digits precision,
// output field width, space or zero padding, and left or
// right justification.
//
func (z *Int) Format(s fmt.State, ch rune) {
base := baseForRune(ch)
// special cases
switch {
case base == 0:
// unknown format
_, _ = fmt.Fprintf(s, "%%!%c(gmp.Int=%s)", ch, z.String())
return
case z == nil:
_, _ = fmt.Fprint(s, "<nil>")
return
}
// determine sign character
sign := ""
switch {
case z.Sign() < 0:
sign = "-"
case s.Flag('+'): // supersedes ' ' when both specified
sign = "+"
case s.Flag(' '):
sign = " "
}
// determine prefix characters for indicating output base
prefix := ""
if s.Flag('#') {
switch ch {
case 'o': // octal
prefix = "0"
case 'x': // hexadecimal
prefix = "0x"
case 'X':
prefix = "0X"
}
}
// determine digits with base set by len(cs) and digit characters from cs
digits := z.string(base)
if digits[0] == '-' {
digits = digits[1:]
}
// number of characters for the three classes of number padding
var left int // space characters to left of digits for right justification ("%8d")
var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
var right int // space characters to right of digits for left justification ("%-8d")
// determine number padding from precision: the least number of digits to output
precision, precisionSet := s.Precision()
if precisionSet {
switch {
case len(digits) < precision:
zeroes = precision - len(digits) // count of zero padding
case digits == "0" && precision == 0:
return // print nothing if zero value (z == 0) and zero precision ("." or ".0")
}
}
// determine field pad from width: the least number of characters to output
length := len(sign) + len(prefix) + zeroes + len(digits)
if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
switch d := width - length; {
case s.Flag('-'):
// pad on the right with spaces; supersedes '0' when both specified
right = d
case s.Flag('0') && !precisionSet:
// pad with zeroes unless precision also specified
zeroes = d
default:
// pad on the left with spaces
left = d
}
}
// print number as [left pad][sign][prefix][zero pad][digits][right pad]
writeMultiple(s, " ", left)
writeMultiple(s, sign, 1)
writeMultiple(s, prefix, 1)
writeMultiple(s, "0", zeroes)
writeMultiple(s, digits, 1)
writeMultiple(s, " ", right)
}
// Scan is a support routine for fmt.Scanner; it sets z to the value of
// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
func (z *Int) Scan(s fmt.ScanState, ch rune) error {
s.SkipSpace() // skip leading space characters
base := 0
switch ch {
case 'b':
base = 2
case 'o':
base = 8
case 'd':
base = 10
case 'x', 'X':
base = 16
case 's', 'v':
// let scan determine the base
default:
return errors.New("Int.Scan: invalid verb")
}
charset := "0123456789abcdef"
if base != 0 {
charset = charset[:base]
}
// Read the number into in
in := make([]byte, 0, 16)
var err error
var n int
for {
ch, n, err = s.ReadRune()
if err == io.EOF {
break
}
if err != nil {
return err
}
if n > 1 {
// Wide character - must be the end
err = s.UnreadRune()
if err != nil {
return err
}
break
}
ch = unicode.ToLower(ch)
if len(in) == 0 {
if ch == '+' {
// Skip leading + as gmp doesn't understand them
continue
}
if ch == '-' {
goto ok
}
}
if len(in) == 1 && base == 0 {
if ch == 'b' || ch == 'x' {
goto ok
}
}
if !strings.ContainsRune(charset, ch) {
// Bad character - end
err = s.UnreadRune()
if err != nil {
return err
}
break
}
ok:
in = append(in, byte(ch))
}
// Use GMP to convert it as it is very efficient for large numbers
z.doinit()
// null terminate for C
in = append(in, 0)
if C.mpz_set_str(&z.i[0], (*C.char)(unsafe.Pointer(&in[0])), C.int(base)) < 0 {
return errors.New("Int.Scan: failed")
}
return nil
}
// Int64 returns the int64 representation of z.
// If z cannot be represented in an int64, the result is undefined.
func (z *Int) Int64() (y int64) {
if !z.init {
return
}
if C.mpz_fits_slong_p(&z.i[0]) != 0 {
return int64(C.mpz_get_si(&z.i[0]))
}
// Undefined result if > 64 bits
if z.BitLen() > 64 {
return
}
C.mpz_export(unsafe.Pointer(&y), nil, -1, 8, 0, 0, &z.i[0])
if z.Sign() < 0 {
y = -y
}
return
}
// Uint64 returns the uint64 representation of z.
// If z cannot be represented in a uint64, the result is undefined.
func (z *Int) Uint64() (y uint64) {
if !z.init {
return
}
if C.mpz_fits_ulong_p(&z.i[0]) != 0 {
return uint64(C.mpz_get_ui(&z.i[0]))
}
// Undefined result if > 64 bits
if z.BitLen() > 64 {
return
}
C.mpz_export(unsafe.Pointer(&y), nil, -1, 8, 0, 0, &z.i[0])
return
}
// SetString sets z to the value of s, interpreted in the given base,
// and returns z and a boolean indicating success. If SetString fails,
// the value of z is undefined but the returned value is nil.
//
// The base argument must be 0 or a value from 2 through MaxBase. If the base
// is 0, the string prefix determines the actual conversion base. A prefix of
// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
//
func (z *Int) SetString(s string, base int) (*Int, bool) {
z.doinit()
if base != 0 && (base < 2 || base > 36) {
return nil, false
}
// Skip leading + as mpz_set_str doesn't understand them
if len(s) > 1 && s[0] == '+' {
s = s[1:]
}
// mpz_set_str incorrectly parses "0x" and "0b" as valid
if base == 0 && len(s) == 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X' || s[1] == 'b' || s[1] == 'B') {
return nil, false
}
p := C.CString(s)
defer C.free(unsafe.Pointer(p))
if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
return nil, false
}
return z, true // err == io.EOF => scan consumed all of s
}
// SetBytes interprets buf as the bytes of a big-endian unsigned
// integer, sets z to that value, and returns z.
func (z *Int) SetBytes(buf []byte) *Int {
z.doinit()
if len(buf) == 0 {
z.SetInt64(0)
} else {
C.mpz_import(&z.i[0], C.size_t(len(buf)), 1, 1, 1, 0, unsafe.Pointer(&buf[0]))
}
return z
}
// Bytes returns the absolute value of z as a big-endian byte slice.
func (z *Int) Bytes() []byte {
b := make([]byte, 1+(z.BitLen()+7)/8)
n := C.size_t(len(b))
C.mpz_export(unsafe.Pointer(&b[0]), &n, 1, 1, 1, 0, &z.i[0])
return b[0:n]
}
// BitLen returns the length of the absolute value of z in bits.
// The bit length of 0 is 0.
func (z *Int) BitLen() int {
z.doinit()
if z.Sign() == 0 {
return 0
}
return int(C.mpz_sizeinbase(&z.i[0], 2))
}
// Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z.
// If y <= 0, the result is 1; if m == nil or m == 0, z = x**y.
// See Knuth, volume 2, section 4.6.3.
func (z *Int) Exp(x, y, m *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
if y.Sign() <= 0 {
z.SetInt64(1)
return z
}
if m == nil || m.Sign() == 0 {
C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]))
} else {
m.doinit()
C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0])
}
return z
}
// GCD sets z to the greatest common divisor of a and b, which both must
// be > 0, and returns z.
// If x and y are not nil, GCD sets x and y such that z = a*x + b*y.
// If either a or b is <= 0, GCD sets z = x = y = 0.
func (z *Int) GCD(x, y, a, b *Int) *Int {
z.doinit()
a.doinit()
b.doinit()
if a.Sign() <= 0 || b.Sign() <= 0 {
z.SetInt64(0)
if x != nil {
x.SetInt64(0)
}
if y != nil {
y.SetInt64(0)
}
} else if x == nil && y == nil {
C.mpz_gcd(&z.i[0], &a.i[0], &b.i[0])
} else {
if x != nil {
x.doinit()
} else {
x = _Int0
}
if y != nil {
y.doinit()
} else {
y = _Int0
}
C.mpz_gcdext(&z.i[0], &x.i[0], &y.i[0], &a.i[0], &b.i[0])
}
return z
}
// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
// If it returns true, z is prime with probability 1 - 1/4^n.
// If it returns false, z is not prime.
func (z *Int) ProbablyPrime(n int) bool {
z.doinit()
return int(C.mpz_probab_prime_p(&z.i[0], C.int(n))) > 0
}
// Rand sets z to a pseudo-random number in [0, n) and returns z.
func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
z.doinit()
// Get rid of n <= 0 case
if n.Sign() <= 0 {
z.SetInt64(0)
return z
}
// Make a copy of n if aliased
t := n
aliased := false
if n == z {
aliased = true
t = new(Int).Set(n)
}
// Work out bit sizes and masks
bits := n.BitLen() // >= 1
nwords := (bits + 31) / 32 // >= 1
bitLengthOfMSW := uint(bits % 32)
if bitLengthOfMSW == 0 {
bitLengthOfMSW = 32
}
mask := uint32((1 << bitLengthOfMSW) - 1)
words := make([]uint32, nwords)
for {
// Make a most significant first array of random bytes
for i := 0; i < nwords; i++ {
words[i] = rnd.Uint32()
}
// Mask out the top bits so this is only just bigger than n
words[0] &= mask
C.mpz_import(&z.i[0], C.size_t(len(words)), 1, 4, 0, 0, unsafe.Pointer(&words[0]))
// Exit if z < n - should take ~1.5 iterations of loop on average
if z.Cmp(t) < 0 {
break
}
}
if aliased {
t.Clear()
}
return z
}
// ModInverse sets z to the multiplicative inverse of g in the group /p (where
// p is a prime) and returns z.
func (z *Int) ModInverse(g, p *Int) *Int {
g.doinit()
p.doinit()
z.doinit()
C.mpz_invert(&z.i[0], &g.i[0], &p.i[0])
return z
}
// Lsh sets z = x << n and returns z.
func (z *Int) Lsh(x *Int, n uint) *Int {
x.doinit()
z.doinit()
C._mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(n))
return z
}
// Rsh sets z = x >> n and returns z.
func (z *Int) Rsh(x *Int, n uint) *Int {
x.doinit()
z.doinit()
C._mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(n))
return z
}
// Bit returns the value of the i'th bit of z. That is, it
// returns (z>>i)&1. The bit index i must be >= 0.
func (z *Int) Bit(i int) uint {
z.doinit()
return uint(C._mpz_tstbit(&z.i[0], C.ulong(i)))
}
// SetBit sets z to x, with x's i'th bit set to b (0 or 1).
// That is, if b is 1 SetBit sets z = x | (1 << i);
// if b is 0 SetBit sets z = x &^ (1 << i). If b is not 0 or 1,
// SetBit will panic.
func (z *Int) SetBit(x *Int, i int, b uint) *Int {
if z != x {
z.Set(x)
}
if b == 0 {
C._mpz_clrbit(&z.i[0], C.ulong(i))
} else {
C._mpz_setbit(&z.i[0], C.ulong(i))
}
return z
}
// And sets z = x & y and returns z.
func (z *Int) And(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
C.mpz_and(&z.i[0], &x.i[0], &y.i[0])
return z
}
// AndNot sets z = x &^ y and returns z.
func (z *Int) AndNot(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
t := z
aliased := false
if z == y || z == x {
aliased = true
t = new(Int).Set(y)
}
C.mpz_com(&t.i[0], &y.i[0])
C.mpz_and(&z.i[0], &x.i[0], &t.i[0])
if aliased {
t.Clear()
}
return z
}
// Or sets z = x | y and returns z.
func (z *Int) Or(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
C.mpz_ior(&z.i[0], &x.i[0], &y.i[0])
return z
}
// Xor sets z = x ^ y and returns z.
func (z *Int) Xor(x, y *Int) *Int {
x.doinit()
y.doinit()
z.doinit()
C.mpz_xor(&z.i[0], &x.i[0], &y.i[0])
return z
}
// Not sets z = ^x and returns z.
func (z *Int) Not(x *Int) *Int {
x.doinit()
z.doinit()
C.mpz_com(&z.i[0], &x.i[0])
return z
}
// Gob codec version. Permits backward-compatible changes to the encoding.
const intGobVersion byte = 1
// GobEncode implements the gob.GobEncoder interface.
func (z *Int) GobEncode() ([]byte, error) {
buf := make([]byte, 2+(z.BitLen()+7)/8)
n := C.size_t(len(buf) - 1)
C.mpz_export(unsafe.Pointer(&buf[1]), &n, 1, 1, 1, 0, &z.i[0])
b := intGobVersion << 1 // make space for sign bit
if z.Sign() < 0 {
b |= 1
}
buf[0] = b
return buf[:n+1], nil
}
// GobDecode implements the gob.GobDecoder interface.
func (z *Int) GobDecode(buf []byte) error {
if len(buf) == 0 {
return errors.New("Int.GobDecode: no data")
}
b := buf[0]
if b>>1 != intGobVersion {
return fmt.Errorf("Int.GobDecode: encoding version %d not supported", b>>1)
}
z.SetBytes(buf[1:])
if b&1 != 0 {
C.mpz_neg(&z.i[0], &z.i[0])
}
return nil
}
// MarshalJSON implements the json.Marshaler interface.
func (z *Int) MarshalJSON() ([]byte, error) {
// TODO(gri): get rid of the []byte/string conversions
return []byte(z.String()), nil
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (z *Int) UnmarshalJSON(x []byte) error {
// TODO(gri): get rid of the []byte/string conversions
_, ok := z.SetString(string(x), 0)
if !ok {
return fmt.Errorf("math/big: cannot unmarshal %s into a *gmp.Int", x)
}
return nil
}