212 lines
4.5 KiB
Go
212 lines
4.5 KiB
Go
// Copyright 2013 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.
|
|
|
|
// Implement extra functionality not in big.Int.
|
|
//
|
|
// Because the underlying C compiler may use 32-bit longs we
|
|
// use 32-bit integers here for maximum portability and speed.
|
|
|
|
//go:build gmp
|
|
// +build gmp
|
|
|
|
package gmp
|
|
|
|
/*
|
|
#cgo LDFLAGS: -lgmp
|
|
#include <gmp.h>
|
|
#include <stdlib.h>
|
|
*/
|
|
import "C"
|
|
|
|
// Sqrt sets x to the truncated integer part of the square root of x
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) Sqrt(x *Int) *Int {
|
|
x.doinit()
|
|
z.doinit()
|
|
C.mpz_sqrt(&z.i[0], &x.i[0])
|
|
return z
|
|
}
|
|
|
|
// Swap exchanges the values of z and x and returns the new z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) Swap(x *Int) *Int {
|
|
x.doinit()
|
|
z.doinit()
|
|
C.mpz_swap(&z.i[0], &x.i[0])
|
|
return z
|
|
}
|
|
|
|
// AddUint32 sets z to the sum x+y and returns z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) AddUint32(x *Int, y uint32) *Int {
|
|
x.doinit()
|
|
z.doinit()
|
|
C.mpz_add_ui(&z.i[0], &x.i[0], C.ulong(y))
|
|
return z
|
|
}
|
|
|
|
// SubUint32 sets z to the difference x-y and returns z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) SubUint32(x *Int, y uint32) *Int {
|
|
x.doinit()
|
|
z.doinit()
|
|
C.mpz_sub_ui(&z.i[0], &x.i[0], C.ulong(y))
|
|
return z
|
|
}
|
|
|
|
// Uint32Sub sets z to the difference x-y and returns z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) Uint32Sub(x uint32, y *Int) *Int {
|
|
y.doinit()
|
|
z.doinit()
|
|
C.mpz_ui_sub(&z.i[0], C.ulong(x), &y.i[0])
|
|
return z
|
|
}
|
|
|
|
// MulUint32 sets z to the product x*y and returns z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) MulUint32(x *Int, y uint32) *Int {
|
|
x.doinit()
|
|
z.doinit()
|
|
C.mpz_mul_ui(&z.i[0], &x.i[0], C.ulong(y))
|
|
return z
|
|
}
|
|
|
|
// MulInt32 sets z to the product x*y and returns z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) MulInt32(x *Int, y int32) *Int {
|
|
x.doinit()
|
|
z.doinit()
|
|
C.mpz_mul_si(&z.i[0], &x.i[0], C.long(y))
|
|
return z
|
|
}
|
|
|
|
// AddMul sets z to z + x*y and returns z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) AddMul(x, y *Int) *Int {
|
|
x.doinit()
|
|
y.doinit()
|
|
z.doinit()
|
|
C.mpz_addmul(&z.i[0], &x.i[0], &y.i[0])
|
|
return z
|
|
}
|
|
|
|
// AddMulUint32 sets z to z + x*y and returns z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) AddMulUint32(x *Int, y uint32) *Int {
|
|
x.doinit()
|
|
z.doinit()
|
|
C.mpz_addmul_ui(&z.i[0], &x.i[0], C.ulong(y))
|
|
return z
|
|
}
|
|
|
|
// SubMul sets z to z - x*y and returns z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) SubMul(x, y *Int) *Int {
|
|
x.doinit()
|
|
y.doinit()
|
|
z.doinit()
|
|
C.mpz_submul(&z.i[0], &x.i[0], &y.i[0])
|
|
return z
|
|
}
|
|
|
|
// SubMulUint32 sets z to z - x*y and returns z.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) SubMulUint32(x *Int, y uint32) *Int {
|
|
x.doinit()
|
|
z.doinit()
|
|
C.mpz_submul_ui(&z.i[0], &x.i[0], C.ulong(y))
|
|
return z
|
|
}
|
|
|
|
// compared reduces the result of a GMP comparison to one of {-1, 0, 1}.
|
|
func compared(i C.int) int {
|
|
if i > 0 {
|
|
return 1
|
|
} else if i < 0 {
|
|
return -1
|
|
} else {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// CmpUint32 compares z and x and returns:
|
|
//
|
|
// -1 if z < x
|
|
// 0 if z == x
|
|
// +1 if z > x
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) CmpUint32(x uint32) int {
|
|
z.doinit()
|
|
return compared(C._mpz_cmp_ui(&z.i[0], C.ulong(x)))
|
|
}
|
|
|
|
// CmpInt32 compares z and x and returns:
|
|
//
|
|
// -1 if z < x
|
|
// 0 if z == x
|
|
// +1 if z > x
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) CmpInt32(x int32) int {
|
|
z.doinit()
|
|
return compared(C._mpz_cmp_si(&z.i[0], C.long(x)))
|
|
}
|
|
|
|
// CmpAbs compares |z| and |x| and returns:
|
|
//
|
|
// -1 if |z| < |x|
|
|
// 0 if |z| == |x|
|
|
// +1 if |z| > |x|
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) CmpAbs(x *Int) int {
|
|
x.doinit()
|
|
z.doinit()
|
|
return compared(C.mpz_cmpabs(&z.i[0], &x.i[0]))
|
|
}
|
|
|
|
// CmpAbsUint32 compares |z| and |x| and returns:
|
|
//
|
|
// -1 if |z| < |x|
|
|
// 0 if |z| == |x|
|
|
// +1 if |z| > |x|
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) CmpAbsUint32(x uint32) int {
|
|
z.doinit()
|
|
return compared(C.mpz_cmpabs_ui(&z.i[0], C.ulong(x)))
|
|
}
|
|
|
|
// Uint32 returns the uint32 representation of z, if z fits into a uint32.
|
|
// If z is too big then the least significant bits that do fit are returned.
|
|
// The sign of z is ignored, only the absolute value is used.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) Uint32() uint32 {
|
|
z.doinit()
|
|
return uint32(C.mpz_get_ui(&z.i[0]))
|
|
}
|
|
|
|
// Int32 returns the int32 representation of z, if z fits into a signed int32.
|
|
// If z is too big to fit in a int32 then the result is undefined.
|
|
//
|
|
// NB This is not part of big.Int
|
|
func (z *Int) Int32() int32 {
|
|
z.doinit()
|
|
return int32(C.mpz_get_si(&z.i[0]))
|
|
}
|