big

package c

import (
"crypto/rand"
"encoding/binary"
"fmt"
"math/big"
"testing"
)

func rands(n uint64) []uint64 {
d := make([]uint64, n)
for i := range d {
d[i] = rand64()
}
return d
}

func rand64() uint64 {
b := make([]byte, 8)
rand.Read(b)
return binary.BigEndian.Uint64(b)
}

func big4(a []uint64) *big.Int {
k := new(big.Int).SetUint64(0)
for i := range a {
k.Lsh(k, 64)
k.Add(k, new(big.Int).SetUint64(a[len(a)-1-i]))
}
return k
}

func big2(a *big.Int) []uint64{
k := []uint64(nil)
for a.Cmp(big.NewInt(0)) > 0 {
k = append(k, a.Uint64())
a.Rsh(a, 64)
}
return k
}

func TestAdd(t *testing.T) {
for i := 0; i < 0xfffff; i++ {
n := rand64() % 20
n2 := rand64() % 20
n++
n2++
a := rands(n)
b := rands(n2)

if big4(big2(new(big.Int).Add(big4(a), big4(b)))).Cmp(big4(add(a, b))) != 0 {
t.Fatal(a, b)
}
}
}

func TestMul(t *testing.T) {
for i := 0; i < 0xfffff; i++ {
n := rand64() % 20
n2 := rand64() % 20
n++
n2++
a := rands(n)
b := rands(n2)

if big4(big2(new(big.Int).Mul(big4(a), big4(b)))).Cmp(big4(mul(a, b))) != 0 {
t.Fatal(a, b)
}
}
}

func TestDiv(t *testing.T) {
for i := 0; i < 0xfffff; i++ {
n := rand64() % 20
n2 := rand64() % 20
n++
n2++
if n < n2 {
n = n2
}
a := rands(n)
b := rands(n2)

q, r := new(big.Int).QuoRem(big4(a), big4(b), new(big.Int))
q2, r2 := div(a, b)

if q.Cmp(big4(q2)) != 0 || r.Cmp(big4(r2)) != 0 {
t.Fatal(a, b)
}
}
}

func TestName(t *testing.T) {
n1 := uint64(0)
n1--
a := []uint64{1, n1, 4}
b := []uint64{9, 4}
q, r := new(big.Int).QuoRem(big4(a), big4(b), new(big.Int))
fmt.Println(big2(q), big2(r))
fmt.Println(div(a, b))
}





package c
/*
#cgo LDFLAGS: -L/Users/jalyzhang/CLionProjects/untitled126 -lh

#include "stdint.h"
#include "sys/types.h"
size_t UAdd(uint64_t* r, const uint64_t *a, size_t an, const uint64_t *b, size_t bn);
ssize_t USub(uint64_t* r, const uint64_t *a, size_t an, const uint64_t *b, size_t bn);
size_t UMul(uint64_t *r, const uint64_t *a, size_t an, const uint64_t *b, size_t bn);
size_t Shr(uint64_t *r, const uint64_t *a, size_t an, size_t n);
size_t Shl(uint64_t *r, const uint64_t *a, size_t an, size_t n);
int UDiv(uint64_t *q, uint64_t *r, const uint64_t *a, size_t an, const uint64_t *b, size_t bn);
int ExpMod(uint64_t *z, const uint64_t *a, size_t an, const uint64_t *x, size_t xn, const uint64_t *m, size_t mn);

static inline int UCmp(const uint64_t *a, size_t an, const uint64_t *b, size_t bn) {
ssize_t i = (ssize_t)an - (ssize_t)bn;
if (i)
return i > 0 ? 1 : -1;
for (i = an - 1; i >= 0; i--) {
uint64_t t1 = a[i];
uint64_t t2 = b[i];
if (t1 != t2)
return ((t1 > t2) ? 1 : -1);
}
return 0;
}

static inline size_t CorrectRet(const uint64_t* rp, size_t rn) {
const uint64_t *ftl;
size_t top = rn;
if (top > 0) {
for (ftl = &(rp[top-1]); top > 0; top--)
if (*(ftl--))
break;
return top;
}
return 0;
}
*/
import "C"

func add(a, b []uint64) []uint64 {
max := len(a)
if max < len(b) {
max = len(b)
}
r := make([]uint64, max)
c := C.UAdd((*C.uint64_t)(&r[0]), (*C.uint64_t)(&a[0]), C.size_t(len(a)), (*C.uint64_t)(&b[0]), C.size_t(len(b)))
if c != 0 {
return append(r, 1)
}
return r
}

func mul(a, b []uint64) []uint64 {
r := make([]uint64, len(a)+len(b))
t := C.UMul((*C.uint64_t)(&r[0]), (*C.uint64_t)(&a[0]), C.size_t(len(a)), (*C.uint64_t)(&b[0]), C.size_t(len(b)))
return r[:C.CorrectRet((*C.uint64_t)(&r[0]), t)]
}

func div(a, b []uint64) ([]uint64, []uint64) {
q := make([]uint64, len(a)-len(b)+1)
r := make([]uint64, len(b))
t := C.UDiv((*C.uint64_t)(&q[0]), (*C.uint64_t)(&r[0]), (*C.uint64_t)(&a[0]), C.size_t(len(a)), (*C.uint64_t)(&b[0]), C.size_t(len(b)))
if t == 0 {
return nil, nil
}
q = q[:C.CorrectRet((*C.uint64_t)(&q[0]), C.size_t(len(q)))]
r = r[:C.CorrectRet((*C.uint64_t)(&r[0]), C.size_t(len(r)))]
return q, r
}





#define add64(r, a) asm volatile("add %1, %0" : "+r"(r) : "X"(a) : "memory")
#define adc64(r, a) asm volatile("adc %1, %0" : "+r"(r) : "X"(a) : "memory")
#define mov(r, a) asm volatile("mov %1, %0" : "=r"(r) : "X"(a) : "memory")
#define clr64(r) mov(r, 0)
#define sub64(r, a) asm volatile("sub %1, %0" : "+r"(r) : "X"(a) : "memory")
#define sbb64(r, a) asm volatile("sbb %1, %0" : "+r"(r) : "X"(a) : "memory")
#define mul64(h, l, a, b) asm volatile("mulx %2, %1, %0" : "=r"(h), "=r"(l) : "r"(b), "d"(a) : "memory")
#define udiv64(q, r, h, l, y) asm volatile("div %4" : "=a"(q), "=d"(r) : "d"(h), "a"(l), "r"(y))

#include "stdint.h"
#include "stdlib.h"
#include "memory.h"
#include "immintrin.h"
static inline size_t clz(uint64_t x) {
return _lzcnt_u64(x);
}


posted @ 2022-08-10 16:17  zJanly  阅读(212)  评论(0编辑  收藏  举报