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
+15
View File
@@ -0,0 +1,15 @@
///
/// Copyright (c) 2018 xdx. All rights reserved.
///
/// \file: doc.go
///
/// \brief:
///
/// \author: xdx
///
/*
Package gmath (mathematical Library) is the basic mathematical library
Named as gmath is easy to auto imports.
*/
package gmath
+17
View File
@@ -0,0 +1,17 @@
package gmath
import (
"xdx.jelly/xgcl/gerrors"
)
//go:generate stringer -type=ErrorCode -linecomment -output=errors_string.go errors.go
type ErrorCode gerrors.ErrorCode
func (e ErrorCode) Error() string {
return gerrors.Format(uint32(e), e.String())
}
// error codes
const (
ErrBufTooShort ErrorCode = 0x0100d000 + iota //缓冲区太小
)
+24
View File
@@ -0,0 +1,24 @@
// Code generated by "stringer -type=ErrorCode -linecomment -output=errors_string.go errors.go"; DO NOT EDIT.
package gmath
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ErrBufTooShort-16830464]
}
const _ErrorCode_name = "缓冲区太小"
var _ErrorCode_index = [...]uint8{0, 15}
func (i ErrorCode) String() string {
i -= 16830464
if i >= ErrorCode(len(_ErrorCode_index)-1) {
return "ErrorCode(" + strconv.FormatInt(int64(i+16830464), 10) + ")"
}
return _ErrorCode_name[_ErrorCode_index[i]:_ErrorCode_index[i+1]]
}
+20
View File
@@ -0,0 +1,20 @@
//go:build !go1.15
// +build !go1.15
package gmath
import (
"math/big"
)
// FillBytes fill the buf with the abs of a in big-endian with zero extention.
// if buf is two short, then return error, while Big.Int's FillBytes panic
func FillBytes(a *big.Int, buf []byte) error {
if (a.BitLen()+7)/8 > len(buf) {
return ErrBufTooShort
}
b := ToNBytes(a, len(buf))
copy(buf, b)
return nil
}
+18
View File
@@ -0,0 +1,18 @@
//go:build go1.15
// +build go1.15
package gmath
import (
"math/big"
)
// FillBytes fill the buf with the abs of a in big-endian with zero extention.
// if buf is too short, then return error, while Big.Int's FillBytes panic
func FillBytes(a *big.Int, buf []byte) error {
if (a.BitLen()+7)/8 > len(buf) {
return ErrBufTooShort
}
a.FillBytes(buf)
return nil
}
+70
View File
@@ -0,0 +1,70 @@
package gmath
import (
"math/big"
)
// BigIntx is a big.Int of x
var (
BigInt0 = big.NewInt(0)
BigInt1 = big.NewInt(1)
BigInt2 = big.NewInt(2)
BigInt3 = big.NewInt(3)
BigInt4 = big.NewInt(4)
BigInt5 = big.NewInt(5)
BigInt6 = big.NewInt(6)
BigInt7 = big.NewInt(7)
BigInt8 = big.NewInt(8)
BigInt9 = big.NewInt(9)
BigInt10 = big.NewInt(10)
BigInt11 = big.NewInt(11)
BigInt12 = big.NewInt(12)
BigInt2256 = new(big.Int).Lsh(BigInt1, 256) // = 2^256
)
// IsBigInt0 return if x==0
func IsBigInt0(x *big.Int) bool {
return x.Sign() == 0
}
// IsBigInt1 return if x==0
func IsBigInt1(x *big.Int) bool {
return x.Cmp(BigInt1) == 0
}
// ClearBigInt set memory of x be 0
func ClearBigInt(x *big.Int) {
if x == nil {
return
}
words := x.Bits()
for i := range words {
words[i] = 0
}
x.SetInt64(0)
}
type bytes interface {
Bytes() []byte
}
// ToNBytes ouput a bytes to fix n bytes. extend as 0.
func ToNBytes(b bytes, n int) []byte {
abs := b.Bytes()
l := len(abs)
var s []byte
// l==n is the most case (255/256)
if l >= n {
s = abs[l-n : l]
} else {
s = make([]byte, n)
copy(s[n-l:], abs)
}
return s
}
// BigIntToNByte return a n byte slice of the input big.Int as big-endian
// if len(a.Bytes()) > n, then only the lower n bytes are return
func BigIntToNByte(a *big.Int, n int) []byte {
return ToNBytes(a, n)
}
+99
View File
@@ -0,0 +1,99 @@
package gmath
import (
stdbytes "bytes"
"crypto/rand"
"fmt"
"math/big"
"os/exec"
"testing"
"xdx.jelly/xgcl/grand"
)
func TestBig(t *testing.T) {
b := grand.Int(0)
fmt.Println(b.Bytes(), b.BitLen())
a := BigInt2256.Neg(BigInt2256)
BigInt2256.Neg(BigInt2256)
b, _ = rand.Int(grand.Reader, a)
fmt.Println(BigInt2256.Text(16))
fmt.Println(b.Text(16))
b, _ = rand.Int(grand.Reader, BigInt2)
fmt.Println(b)
}
func TestFillBytes(t *testing.T) {
a, _ := new(big.Int).SetString("123455", 16)
buf := make([]byte, 1)
// buf[2] = 1
fmt.Printf("%02x\n", buf)
err := FillBytes(a, buf)
fmt.Printf("%02x %v\n", buf, err)
fmt.Println("over")
}
func opensslIsPrime(n *big.Int) bool {
cmd := exec.Command("openssl", "prime", "-hex", n.Text(16))
buf, err := cmd.Output()
if err != nil || stdbytes.Contains(buf, []byte("not prime")) {
return false
}
return true
}
func TestIsPrimeMR(t *testing.T) {
bits := 1024
n := grand.Int(bits)
count := 1
for !IsPrimeMR(n) {
count++
n = grand.Int(bits)
}
fmt.Println("random times: ", count)
fmt.Println(n.Text(16))
if !opensslIsPrime(n) {
t.Fail()
}
}
func TestZp(t *testing.T) {
defer func() {
if err := recover(); err != nil {
fmt.Println("panic:", err)
fmt.Println("recover")
}
}()
p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
a := NewZp(p)
b := NewZp(p)
c := NewZp(p)
a.SetString("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16)
b.SetString("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16)
c.Add(a, b)
fmt.Println("a+b= ", c)
c.Sub(b, a)
fmt.Println("b-a= ", c)
c.Mul(b, a)
fmt.Println("a*b= ", c)
c.Inv(b)
fmt.Println("b^(-1)=", c)
b.SetInt(0)
c.Inv(b)
fmt.Println("0^(-1)=", c)
}
func TestRandom(t *testing.T) {
p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
a := NewZp(p)
if err := a.Random(); err != nil {
t.Failed()
}
}
+48
View File
@@ -0,0 +1,48 @@
package gmath
import (
"crypto/rand"
"math/big"
"xdx.jelly/xgcl/grand"
)
const MRConst = 10
// IsPrimeMR tests if n is prime by the Miller-Rabin prime testing method.
func IsPrimeMR(n *big.Int) bool {
return n.ProbablyPrime(MRConst)
}
// MillerRabin tests if n is prime by the Miller-Rabin prime testing method.
func MillerRabin(n *big.Int) bool {
// n = 2^s * r
n1 := new(big.Int)
n1.Sub(n, BigInt1)
r := new(big.Int).Set(n1)
s := 0
for r.Bit(0) == 0 {
s++
r = r.Rsh(r, 1)
}
for i := 0; i < MRConst; i++ {
a, _ := rand.Int(grand.Reader, n1)
//a = a^r mod n
a.Exp(a, r, n)
if a.Cmp(BigInt1) != 0 && a.Cmp(n1) != 0 {
for j := 1; j < s && a.Cmp(n1) != 0; j++ {
a.Mul(a, a)
a.Mod(a, n)
if a.Cmp(BigInt1) == 0 {
return false
}
}
if a.Cmp(n1) != 0 {
return false
}
}
}
return true
}
+236
View File
@@ -0,0 +1,236 @@
package gmath
import (
"crypto/rand"
"encoding/hex"
"math/big"
"xdx.jelly/xgcl/grand"
)
// Zp is a simple wrap of big.Int, to comput in integers mod p
type Zp struct {
d *big.Int
p *big.Int
byteSize int
}
func (z *Zp) init(p *big.Int) *Zp {
z.d = new(big.Int)
z.p = p
z.byteSize = len(z.p.Bytes())
return z
}
// a to bytes slice, big endian, padding 0
// 0x123456 =>
// 00 00 00 00 ... 12 34 56 78 -- total nBytes
// note:
// if a.Bytes() are longer than nBytes, then
// only the nBytes of lower are return. i.e
// the return value is a mod 2^{8*nBytes}
func intToByte(a *big.Int, nBytes int) []byte {
abs := a.Bytes()
l := len(abs)
s := make([]byte, nBytes)
if nBytes > l {
copy(s[nBytes-l:], abs)
} else {
copy(s, abs[l-nBytes:])
}
return s
}
// NewZp ...
func NewZp(p *big.Int) *Zp {
return new(Zp).init(p)
}
// Clear set memory to 0
func (z *Zp) Clear() {
abs := z.d.Bytes()
for i := range abs {
abs[i] = 0
}
z.SetInt(0)
}
// GetInteger return the d (0 < d < p)
func (z *Zp) GetInteger() *big.Int {
return z.Normalize().d
}
// GetPrime return the p
func (z *Zp) GetPrime() *big.Int {
return z.p
}
// Set z to x
func (z *Zp) Set(x *Zp) *Zp {
z.d.Set(x.d)
z.p = x.p
return z
}
// SetInt ...
func (z *Zp) SetInt(n int) *Zp {
z.d.SetInt64(int64(n))
return z
}
// SetBigInt ...
func (z *Zp) SetBigInt(n *big.Int) *Zp {
z.d.Set(n)
return z
}
// SetString ...
func (z *Zp) SetString(s string, base int) (*Zp, bool) {
_, err := z.d.SetString(s, base)
return z, err
}
// SetBytes ...
func (z *Zp) SetBytes(buf []byte) *Zp {
z.d.SetBytes(buf)
return z
}
// Is0 ...
func (z *Zp) Is0() bool {
z.Normalize()
return IsBigInt0(z.d)
}
// Is1 ...
func (z *Zp) Is1() bool {
z.Normalize()
return IsBigInt1(z.d)
}
// Sign return the odd of z.d
func (z *Zp) Sign() uint {
return z.Normalize().d.Bit(0)
}
// Equal ...
func (z *Zp) Equal(p *Zp) bool {
return z.Normalize().d.Cmp(p.Normalize().d) == 0
}
// GetItem return the d, this is for a extension field,
// the d is an array, and return the d[i]
func (z *Zp) GetItem(i int) *big.Int {
if i == 0 {
return z.d
}
return nil
}
// Normalize put d to [0,p-1]
func (z *Zp) Normalize() *Zp {
z.d.Mod(z.d, z.p)
return z
}
// Bytes return the byte slice of z.d, with a const slice size with p.Bytes()
func (z *Zp) Bytes() []byte {
z.Normalize()
return intToByte(z.d, z.byteSize)
}
func (z *Zp) String() string {
return hex.EncodeToString(z.Bytes())
}
// Add z = p+q
// make sure that z,p,q are in the same field, or the result is a shit
func (z *Zp) Add(p, q *Zp) *Zp {
pp := p.d
qq := q.d
z.d.Add(pp, qq)
return z
}
// AddInt z = p+n
func (z *Zp) AddInt(p *Zp, n int) *Zp {
z.d.Add(p.d, big.NewInt(int64(n)))
return z
}
// AddBigInt ...
func (z *Zp) AddBigInt(p *Zp, n *big.Int) *Zp {
z.d.Add(p.d, n)
return z
}
// Neg ...
func (z *Zp) Neg(p *Zp) *Zp {
p.Normalize() // p maybe changed, but not matter
if !p.Is0() {
z.d.Sub(z.d, p.d)
} else {
z.Set(p)
}
return z
}
// Sub ...
func (z *Zp) Sub(p, q *Zp) *Zp {
z.d.Sub(p.d, q.d)
return z
}
// SubInt ...
func (z *Zp) SubInt(p *Zp, n int) *Zp {
z.d.Sub(p.d, big.NewInt(int64(n)))
return z
}
// SubBigInt ...
func (z *Zp) SubBigInt(p *Zp, n *big.Int) *Zp {
z.d.Sub(p.d, n)
return z
}
// Mul ...
func (z *Zp) Mul(p, q *Zp) *Zp {
p.Normalize()
q.Normalize()
z.d.Mul(p.d, q.d)
z.Normalize()
return z
}
// MulInt ...
func (z *Zp) MulInt(p *Zp, n int) *Zp {
z.d.Mul(p.d, big.NewInt(int64(n)))
z.Normalize()
return z
}
// MulBigInt ...
func (z *Zp) MulBigInt(p *Zp, n *big.Int) *Zp {
z.d.Mul(p.d, n)
z.Normalize()
return z
}
// Inv z=p^(-1), if p == 0, panic
func (z *Zp) Inv(p *Zp) *Zp {
if p.Is0() {
panic("zp:Inv try to invert 0")
}
z.d.ModInverse(p.d, z.p)
return z
}
// Random return a random number from entropy
func (z *Zp) Random() error {
n, err := rand.Int(grand.Reader, z.p)
if err != nil {
return err
}
z.d = n
return nil
}