2009-08-24 22:16:15 -06:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <gmp.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
typedef int32_t int32;
|
2009-08-25 16:37:22 -06:00
|
|
|
typedef uint32_t uint32;
|
|
|
|
typedef int64_t int64;
|
2009-08-24 22:16:15 -06:00
|
|
|
typedef uint64_t uint64;
|
|
|
|
|
2009-08-25 16:37:22 -06:00
|
|
|
typedef struct Slice Slice;
|
|
|
|
struct Slice
|
|
|
|
{
|
|
|
|
void *data;
|
|
|
|
uint32 len;
|
|
|
|
uint32 cap;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct String String;
|
|
|
|
struct String
|
|
|
|
{
|
|
|
|
void *data;
|
|
|
|
uint32 len;
|
|
|
|
};
|
|
|
|
|
2009-08-24 22:16:15 -06:00
|
|
|
typedef struct Int Int;
|
|
|
|
struct Int
|
|
|
|
{
|
|
|
|
mpz_t *mp;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_newInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
uint64 x;
|
|
|
|
Int *z;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->z->mp = malloc(sizeof *a->z->mp);
|
|
|
|
mpz_init_set_ui(*a->z->mp, a->x);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_addInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *y;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_add(*a->z->mp, *a->x->mp, *a->y->mp);
|
|
|
|
}
|
|
|
|
|
2009-08-25 16:37:22 -06:00
|
|
|
void
|
|
|
|
gmp_subInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *y;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_sub(*a->z->mp, *a->x->mp, *a->y->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_mulInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *y;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_mul(*a->z->mp, *a->x->mp, *a->y->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_setInt64Int(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
int64 x;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_set_si(*a->z->mp, a->x);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_int64Int(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
int64 ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = mpz_get_si(*a->z->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_divInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *y;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_div(*a->z->mp, *a->x->mp, *a->y->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_modInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *y;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_mod(*a->z->mp, *a->x->mp, *a->y->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_divModInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *d;
|
|
|
|
Int *m;
|
|
|
|
Int *x;
|
|
|
|
Int *y;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
mpz_tdiv_qr(*a->d->mp, *a->m->mp, *a->x->mp, *a->y->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_lshInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
uint32 s;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_mul_2exp(*a->z->mp, *a->x->mp, a->s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_rshInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
int32 s;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_div_2exp(*a->z->mp, *a->x->mp, a->s);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_expInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *y;
|
|
|
|
Int *w;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_powm(*a->z->mp, *a->x->mp, *a->y->mp, *a->w->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_gcdInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *y;
|
|
|
|
Int *a;
|
|
|
|
Int *b;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_gcdext(*a->z->mp, *a->x->mp, *a->y->mp, *a->a->mp, *a->b->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_negInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_neg(*a->z->mp, *a->x->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_absInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_abs(*a->z->mp, *a->x->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_cmpInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *x;
|
|
|
|
Int *y;
|
|
|
|
int32 ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = mpz_cmp(*a->x->mp, *a->y->mp);
|
|
|
|
}
|
|
|
|
|
2009-08-24 22:16:15 -06:00
|
|
|
void
|
|
|
|
gmp_stringInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
char *p;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->p = mpz_get_str(NULL, 10, *a->z->mp);
|
|
|
|
}
|
|
|
|
|
2009-08-25 16:37:22 -06:00
|
|
|
void
|
|
|
|
gmp_setInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Int *x;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_set(*a->z->mp, *a->x->mp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_setBytesInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Slice b;
|
|
|
|
Int *ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = a->z;
|
|
|
|
mpz_import(*a->z->mp, a->b.len, 1, 1, 1, 0, a->b.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_lenInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
int32 ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = mpz_sizeinbase(*a->z->mp, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_bytesInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
Slice b;
|
|
|
|
} *a = v;
|
|
|
|
size_t n;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
n = (mpz_sizeinbase(*a->z->mp, 2) + 7) >> 3;
|
|
|
|
p = malloc(n); // TODO: mallocgc
|
|
|
|
mpz_export(p, &n, 1, 1, 1, 0, *a->z->mp);
|
|
|
|
a->b.data = p;
|
|
|
|
a->b.len = n;
|
|
|
|
a->b.cap = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_setStringInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
String s;
|
|
|
|
int32 base;
|
|
|
|
int32 pad;
|
|
|
|
int32 ret;
|
|
|
|
} *a = v;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
p = malloc(a->s.len+1);
|
|
|
|
memmove(p, a->s.data, a->s.len);
|
|
|
|
p[a->s.len] = 0;
|
|
|
|
a->ret = mpz_set_str(*a->z->mp, p, a->base);
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gmp_probablyPrimeInt(void *v)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
Int *z;
|
|
|
|
int32 nreps;
|
|
|
|
int32 pad;
|
|
|
|
int32 ret;
|
|
|
|
} *a = v;
|
|
|
|
|
|
|
|
a->ret = mpz_probab_prime_p(*a->z->mp, a->nreps);
|
|
|
|
}
|
|
|
|
|