Home | History | Annotate | Download | only in gmp
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 /*
      6 An example of wrapping a C library in Go. This is the GNU
      7 multiprecision library gmp's integer type mpz_t wrapped to look like
      8 the Go package big's integer type Int.
      9 
     10 This is a syntactically valid Go programit can be parsed with the Go
     11 parser and processed by godocbut it is not compiled directly by gc.
     12 Instead, a separate tool, cgo, processes it to produce three output
     13 files.  The first two, 6g.go and 6c.c, are a Go source file for 6g and
     14 a C source file for 6c; both compile as part of the named package
     15 (gmp, in this example).  The third, gcc.c, is a C source file for gcc;
     16 it compiles into a shared object (.so) that is dynamically linked into
     17 any 6.out that imports the first two files.
     18 
     19 The stanza
     20 
     21 	// #include <gmp.h>
     22 	import "C"
     23 
     24 is a signal to cgo.  The doc comment on the import of "C" provides
     25 additional context for the C file.  Here it is just a single #include
     26 but it could contain arbitrary C definitions to be imported and used.
     27 
     28 Cgo recognizes any use of a qualified identifier C.xxx and uses gcc to
     29 find the definition of xxx.  If xxx is a type, cgo replaces C.xxx with
     30 a Go translation.  C arithmetic types translate to precisely-sized Go
     31 arithmetic types.  A C struct translates to a Go struct, field by
     32 field; unrepresentable fields are replaced with opaque byte arrays.  A
     33 C union translates into a struct containing the first union member and
     34 perhaps additional padding.  C arrays become Go arrays.  C pointers
     35 become Go pointers.  C function pointers become Go's uintptr.
     36 C void pointers become Go's unsafe.Pointer.
     37 
     38 For example, mpz_t is defined in <gmp.h> as:
     39 
     40 	typedef unsigned long int mp_limb_t;
     41 
     42 	typedef struct
     43 	{
     44 		int _mp_alloc;
     45 		int _mp_size;
     46 		mp_limb_t *_mp_d;
     47 	} __mpz_struct;
     48 
     49 	typedef __mpz_struct mpz_t[1];
     50 
     51 Cgo generates:
     52 
     53 	type _C_int int32
     54 	type _C_mp_limb_t uint64
     55 	type _C___mpz_struct struct {
     56 		_mp_alloc _C_int;
     57 		_mp_size _C_int;
     58 		_mp_d *_C_mp_limb_t;
     59 	}
     60 	type _C_mpz_t [1]_C___mpz_struct
     61 
     62 and then replaces each occurrence of a type C.xxx with _C_xxx.
     63 
     64 If xxx is data, cgo arranges for C.xxx to refer to the C variable,
     65 with the type translated as described above.  To do this, cgo must
     66 introduce a Go variable that points at the C variable (the linker can
     67 be told to initialize this pointer).  For example, if the gmp library
     68 provided
     69 
     70 	mpz_t zero;
     71 
     72 then cgo would rewrite a reference to C.zero by introducing
     73 
     74 	var _C_zero *C.mpz_t
     75 
     76 and then replacing all instances of C.zero with (*_C_zero).
     77 
     78 Cgo's most interesting translation is for functions.  If xxx is a C
     79 function, then cgo rewrites C.xxx into a new function _C_xxx that
     80 calls the C xxx in a standard pthread.  The new function translates
     81 its arguments, calls xxx, and translates the return value.
     82 
     83 Translation of parameters and the return value follows the type
     84 translation above except that arrays passed as parameters translate
     85 explicitly in Go to pointers to arrays, as they do (implicitly) in C.
     86 
     87 Garbage collection is the big problem.  It is fine for the Go world to
     88 have pointers into the C world and to free those pointers when they
     89 are no longer needed.  To help, the Go code can define Go objects
     90 holding the C pointers and use runtime.SetFinalizer on those Go objects.
     91 
     92 It is much more difficult for the C world to have pointers into the Go
     93 world, because the Go garbage collector is unaware of the memory
     94 allocated by C.  The most important consideration is not to
     95 constrain future implementations, so the rule is that Go code can
     96 hand a Go pointer to C code but must separately arrange for
     97 Go to hang on to a reference to the pointer until C is done with it.
     98 */
     99 package gmp
    100 
    101 /*
    102 #cgo LDFLAGS: -lgmp
    103 #include <gmp.h>
    104 #include <stdlib.h>
    105 
    106 // gmp 5.0.0+ changed the type of the 3rd argument to mp_bitcnt_t,
    107 // so, to support older versions, we wrap these two functions.
    108 void _mpz_mul_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
    109 	mpz_mul_2exp(a, b, n);
    110 }
    111 void _mpz_div_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
    112 	mpz_div_2exp(a, b, n);
    113 }
    114 */
    115 import "C"
    116 
    117 import (
    118 	"os"
    119 	"unsafe"
    120 )
    121 
    122 /*
    123  * one of a kind
    124  */
    125 
    126 // An Int represents a signed multi-precision integer.
    127 // The zero value for an Int represents the value 0.
    128 type Int struct {
    129 	i    C.mpz_t
    130 	init bool
    131 }
    132 
    133 // NewInt returns a new Int initialized to x.
    134 func NewInt(x int64) *Int { return new(Int).SetInt64(x) }
    135 
    136 // Int promises that the zero value is a 0, but in gmp
    137 // the zero value is a crash.  To bridge the gap, the
    138 // init bool says whether this is a valid gmp value.
    139 // doinit initializes z.i if it needs it.  This is not inherent
    140 // to FFI, just a mismatch between Go's convention of
    141 // making zero values useful and gmp's decision not to.
    142 func (z *Int) doinit() {
    143 	if z.init {
    144 		return
    145 	}
    146 	z.init = true
    147 	C.mpz_init(&z.i[0])
    148 }
    149 
    150 // Bytes returns z's representation as a big-endian byte array.
    151 func (z *Int) Bytes() []byte {
    152 	b := make([]byte, (z.Len()+7)/8)
    153 	n := C.size_t(len(b))
    154 	C.mpz_export(unsafe.Pointer(&b[0]), &n, 1, 1, 1, 0, &z.i[0])
    155 	return b[0:n]
    156 }
    157 
    158 // Len returns the length of z in bits.  0 is considered to have length 1.
    159 func (z *Int) Len() int {
    160 	z.doinit()
    161 	return int(C.mpz_sizeinbase(&z.i[0], 2))
    162 }
    163 
    164 // Set sets z = x and returns z.
    165 func (z *Int) Set(x *Int) *Int {
    166 	z.doinit()
    167 	C.mpz_set(&z.i[0], &x.i[0])
    168 	return z
    169 }
    170 
    171 // SetBytes interprets b as the bytes of a big-endian integer
    172 // and sets z to that value.
    173 func (z *Int) SetBytes(b []byte) *Int {
    174 	z.doinit()
    175 	if len(b) == 0 {
    176 		z.SetInt64(0)
    177 	} else {
    178 		C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0]))
    179 	}
    180 	return z
    181 }
    182 
    183 // SetInt64 sets z = x and returns z.
    184 func (z *Int) SetInt64(x int64) *Int {
    185 	z.doinit()
    186 	// TODO(rsc): more work on 32-bit platforms
    187 	C.mpz_set_si(&z.i[0], C.long(x))
    188 	return z
    189 }
    190 
    191 // SetString interprets s as a number in the given base
    192 // and sets z to that value.  The base must be in the range [2,36].
    193 // SetString returns an error if s cannot be parsed or the base is invalid.
    194 func (z *Int) SetString(s string, base int) error {
    195 	z.doinit()
    196 	if base < 2 || base > 36 {
    197 		return os.ErrInvalid
    198 	}
    199 	p := C.CString(s)
    200 	defer C.free(unsafe.Pointer(p))
    201 	if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
    202 		return os.ErrInvalid
    203 	}
    204 	return nil
    205 }
    206 
    207 // String returns the decimal representation of z.
    208 func (z *Int) String() string {
    209 	if z == nil {
    210 		return "nil"
    211 	}
    212 	z.doinit()
    213 	p := C.mpz_get_str(nil, 10, &z.i[0])
    214 	s := C.GoString(p)
    215 	C.free(unsafe.Pointer(p))
    216 	return s
    217 }
    218 
    219 func (z *Int) destroy() {
    220 	if z.init {
    221 		C.mpz_clear(&z.i[0])
    222 	}
    223 	z.init = false
    224 }
    225 
    226 /*
    227  * arithmetic
    228  */
    229 
    230 // Add sets z = x + y and returns z.
    231 func (z *Int) Add(x, y *Int) *Int {
    232 	x.doinit()
    233 	y.doinit()
    234 	z.doinit()
    235 	C.mpz_add(&z.i[0], &x.i[0], &y.i[0])
    236 	return z
    237 }
    238 
    239 // Sub sets z = x - y and returns z.
    240 func (z *Int) Sub(x, y *Int) *Int {
    241 	x.doinit()
    242 	y.doinit()
    243 	z.doinit()
    244 	C.mpz_sub(&z.i[0], &x.i[0], &y.i[0])
    245 	return z
    246 }
    247 
    248 // Mul sets z = x * y and returns z.
    249 func (z *Int) Mul(x, y *Int) *Int {
    250 	x.doinit()
    251 	y.doinit()
    252 	z.doinit()
    253 	C.mpz_mul(&z.i[0], &x.i[0], &y.i[0])
    254 	return z
    255 }
    256 
    257 // Div sets z = x / y, rounding toward zero, and returns z.
    258 func (z *Int) Div(x, y *Int) *Int {
    259 	x.doinit()
    260 	y.doinit()
    261 	z.doinit()
    262 	C.mpz_tdiv_q(&z.i[0], &x.i[0], &y.i[0])
    263 	return z
    264 }
    265 
    266 // Mod sets z = x % y and returns z.
    267 // Like the result of the Go % operator, z has the same sign as x.
    268 func (z *Int) Mod(x, y *Int) *Int {
    269 	x.doinit()
    270 	y.doinit()
    271 	z.doinit()
    272 	C.mpz_tdiv_r(&z.i[0], &x.i[0], &y.i[0])
    273 	return z
    274 }
    275 
    276 // Lsh sets z = x << s and returns z.
    277 func (z *Int) Lsh(x *Int, s uint) *Int {
    278 	x.doinit()
    279 	z.doinit()
    280 	C._mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
    281 	return z
    282 }
    283 
    284 // Rsh sets z = x >> s and returns z.
    285 func (z *Int) Rsh(x *Int, s uint) *Int {
    286 	x.doinit()
    287 	z.doinit()
    288 	C._mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
    289 	return z
    290 }
    291 
    292 // Exp sets z = x^y % m and returns z.
    293 // If m == nil, Exp sets z = x^y.
    294 func (z *Int) Exp(x, y, m *Int) *Int {
    295 	m.doinit()
    296 	x.doinit()
    297 	y.doinit()
    298 	z.doinit()
    299 	if m == nil {
    300 		C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]))
    301 	} else {
    302 		C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0])
    303 	}
    304 	return z
    305 }
    306 
    307 func (z *Int) Int64() int64 {
    308 	if !z.init {
    309 		return 0
    310 	}
    311 	return int64(C.mpz_get_si(&z.i[0]))
    312 }
    313 
    314 // Neg sets z = -x and returns z.
    315 func (z *Int) Neg(x *Int) *Int {
    316 	x.doinit()
    317 	z.doinit()
    318 	C.mpz_neg(&z.i[0], &x.i[0])
    319 	return z
    320 }
    321 
    322 // Abs sets z to the absolute value of x and returns z.
    323 func (z *Int) Abs(x *Int) *Int {
    324 	x.doinit()
    325 	z.doinit()
    326 	C.mpz_abs(&z.i[0], &x.i[0])
    327 	return z
    328 }
    329 
    330 /*
    331  * functions without a clear receiver
    332  */
    333 
    334 // CmpInt compares x and y. The result is
    335 //
    336 //   -1 if x <  y
    337 //    0 if x == y
    338 //   +1 if x >  y
    339 //
    340 func CmpInt(x, y *Int) int {
    341 	x.doinit()
    342 	y.doinit()
    343 	switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); {
    344 	case cmp < 0:
    345 		return -1
    346 	case cmp == 0:
    347 		return 0
    348 	}
    349 	return +1
    350 }
    351 
    352 // DivModInt sets q = x / y and r = x % y.
    353 func DivModInt(q, r, x, y *Int) {
    354 	q.doinit()
    355 	r.doinit()
    356 	x.doinit()
    357 	y.doinit()
    358 	C.mpz_tdiv_qr(&q.i[0], &r.i[0], &x.i[0], &y.i[0])
    359 }
    360 
    361 // GcdInt sets d to the greatest common divisor of a and b,
    362 // which must be positive numbers.
    363 // If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y.
    364 // If either a or b is not positive, GcdInt sets d = x = y = 0.
    365 func GcdInt(d, x, y, a, b *Int) {
    366 	d.doinit()
    367 	x.doinit()
    368 	y.doinit()
    369 	a.doinit()
    370 	b.doinit()
    371 	C.mpz_gcdext(&d.i[0], &x.i[0], &y.i[0], &a.i[0], &b.i[0])
    372 }
    373 
    374 // ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
    375 // If it returns true, z is prime with probability 1 - 1/4^n.
    376 // If it returns false, z is not prime.
    377 func (z *Int) ProbablyPrime(n int) bool {
    378 	z.doinit()
    379 	return int(C.mpz_probab_prime_p(&z.i[0], C.int(n))) > 0
    380 }
    381