diff --git a/_cmptest/bigintdemo/fib.go b/_cmptest/bigintdemo/fib.go index 9876c2e0..23a3d5a4 100644 --- a/_cmptest/bigintdemo/fib.go +++ b/_cmptest/bigintdemo/fib.go @@ -5,7 +5,7 @@ import ( "math/big" ) -func main() { +func fib() { // Initialize two big ints with the first two numbers in the sequence. a := big.NewInt(0) b := big.NewInt(1) @@ -23,3 +23,41 @@ func main() { } fmt.Println(a) // 100-digit Fibonacci number } + +func abs() { + a := big.NewInt(64) + b := big.NewInt(-52) + a.Set(b) + a.Abs(a) + a.Set(big.NewInt(-164)) + a.Abs(a) + fmt.Println("value: ", a.String()) +} + +func neg() { + fmt.Println("value: ", big.NewInt(-64).Neg(big.NewInt(-64))) + fmt.Println("value: ", big.NewInt(64).Neg(big.NewInt(64))) + fmt.Println("value: ", big.NewInt(0).Neg(big.NewInt(0))) +} + +func calc() { + a := big.NewInt(64) + b := big.NewInt(-52) + c := big.NewInt(54) + fmt.Println("value:", a.Add(a, b)) + fmt.Println("value:", a.Sub(b, c)) + d := big.NewInt(10) + e := big.NewInt(4) + fmt.Println("value:", d.Mul(d, e)) +} + +func bitop() { + a := big.NewInt(4) + fmt.Println("value:", a.Lsh(a, 1)) + b := big.NewInt(16) + fmt.Println("value:", b.Rsh(b, 2)) +} + +func main() { + bitop() +} diff --git a/c/openssl/bn.go b/c/openssl/bn.go index 4a765b1c..37cf3452 100644 --- a/c/openssl/bn.go +++ b/c/openssl/bn.go @@ -49,8 +49,19 @@ func BN_CTXSecureNew() *BN_CTX func (*BN_CTX) Free() {} // void BN_CTX_start(BN_CTX *ctx); +// +// llgo:link (*BN_CTX).Start C.BN_CTX_start +func (*BN_CTX) Start() {} + // BIGNUM *BN_CTX_get(BN_CTX *ctx); +// +// llgo:link (*BN_CTX).Get C.BN_CTX_get +func (*BN_CTX) Get() *BIGNUM { return nil } + // void BN_CTX_end(BN_CTX *ctx); +// +// llgo:link (*BN_CTX).End C.BN_CTX_end +func (*BN_CTX) End() {} // ----------------------------------------------------------------------------- @@ -191,23 +202,80 @@ func BNDec2bn(a **BIGNUM, str *c.Char) c.Int //go:linkname BNAsc2bn C.BN_asc2bn func BNAsc2bn(a **BIGNUM, str *c.Char) c.Int -/* -BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); -BIGNUM *BN_signed_bin2bn(const unsigned char *s, int len, BIGNUM *ret); -int BN_bn2bin(const BIGNUM *a, unsigned char *to); -int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); -int BN_signed_bn2bin(const BIGNUM *a, unsigned char *to, int tolen); -BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret); -BIGNUM *BN_signed_lebin2bn(const unsigned char *s, int len, BIGNUM *ret); -int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen); -int BN_signed_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen); -BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret); -BIGNUM *BN_signed_native2bn(const unsigned char *s, int len, BIGNUM *ret); -int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen); -int BN_signed_bn2native(const BIGNUM *a, unsigned char *to, int tolen); -BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret); -int BN_bn2mpi(const BIGNUM *a, unsigned char *to); -*/ +// BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +// +//go:linkname BNBin2bn C.BN_bin2bn +func BNBin2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM + +// BIGNUM *BN_signed_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +// +//go:linkname BNSignedBin2bn C.BN_signed_bin2bn +func BNSignedBin2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM + +// int BN_bn2bin(const BIGNUM *a, unsigned char *to); +// +// llgo:link (*BIGNUM).Bn2bin C.BN_bn2bin +func (bn *BIGNUM) Bn2bin(to *byte) c.Int { return 0 } + +// int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); +// +// llgo:link (*BIGNUM).Bn2binpad C.BN_bn2binpad +func (bn *BIGNUM) Bn2binpad(to *byte, tolen c.Int) c.Int { return 0 } + +// int BN_signed_bn2bin(const BIGNUM *a, unsigned char *to, int tolen); +// +// llgo:link (*BIGNUM).SignedBn2bin C.BN_signed_bn2bin +func (bn *BIGNUM) SignedBn2bin(to *byte, tolen c.Int) c.Int { return 0 } + +// BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret); +// +//go:linkname BNLebin2bn C.BN_lebin2bn +func BNLebin2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM + +// BIGNUM *BN_signed_lebin2bn(const unsigned char *s, int len, BIGNUM *ret); +// +//go:linkname BNSignedLebin2bn C.BN_signed_lebin2bn +func BNSignedLebin2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM + +// int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen); +// +// llgo:link (*BIGNUM).Bn2lebinpad C.BN_bn2lebinpad +func (bn *BIGNUM) Bn2lebinpad(to *byte, tolen c.Int) c.Int { return 0 } + +// int BN_signed_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen); +// +// llgo:link (*BIGNUM).SignedBn2lebin C.BN_signed_bn2lebin +func (bn *BIGNUM) SignedBn2lebin(to *byte, tolen c.Int) c.Int { return 0 } + +// BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret); +// +//go:linkname BNNative2bn C.BN_native2bn +func BNNative2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM + +// BIGNUM *BN_signed_native2bn(const unsigned char *s, int len, BIGNUM *ret); +// +//go:linkname BNSignedNative2bn C.BN_signed_native2bn +func BNSignedNative2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM + +// int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen); +// +// llgo:link (*BIGNUM).Bn2nativepad C.BN_bn2nativepad +func (bn *BIGNUM) Bn2nativepad(to *byte, tolen c.Int) c.Int { return 0 } + +// int BN_signed_bn2native(const BIGNUM *a, unsigned char *to, int tolen); +// +// llgo:link (*BIGNUM).SignedBn2native C.BN_signed_bn2native +func (bn *BIGNUM) SignedBn2native(to *byte, tolen c.Int) c.Int { return 0 } + +// BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret); +// +//go:linkname BNMpi2bn C.BN_mpi2bn +func BNMpi2bn(s *byte, len c.Int, ret *BIGNUM) *BIGNUM + +// int BN_bn2mpi(const BIGNUM *a, unsigned char *to); +// +// llgo:link (*BIGNUM).Bn2mpi C.BN_bn2mpi +func (bn *BIGNUM) Bn2mpi(to *byte) c.Int { return 0 } // int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); // diff --git a/internal/lib/math/big/int.go b/internal/lib/math/big/int.go index f568938b..e0bbbfe1 100644 --- a/internal/lib/math/big/int.go +++ b/internal/lib/math/big/int.go @@ -18,6 +18,9 @@ package big // llgo:skipall import ( + "math/rand" + + "github.com/goplus/llgo/c" "github.com/goplus/llgo/c/openssl" ) @@ -81,9 +84,34 @@ func NewInt(x int64) *Int { return z.SetInt64(x) } -/* // Set sets z to x and returns z. func (z *Int) Set(x *Int) *Int { + if z != x { + a := (*openssl.BIGNUM)(z) + b := (*openssl.BIGNUM)(x) + a.Copy(b) + } + return z +} + +// Abs sets z to |x| (the absolute value of x) and returns z. +func (z *Int) Abs(x *Int) *Int { + z.Set(x) + a := (*openssl.BIGNUM)(z) + a.SetNegative(0) + return z +} + +// Neg sets z to -x and returns z. +func (z *Int) Neg(x *Int) *Int { + z.Set(x) + a := (*openssl.BIGNUM)(z) + if a.IsNegative() != 0 { + a.SetNegative(0) + } else { + a.SetNegative(1) + } + return z } // Bits provides raw (unchecked but fast) access to x by returning its @@ -92,6 +120,7 @@ func (z *Int) Set(x *Int) *Int { // Bits is intended to support implementation of missing low-level Int // functionality outside this package; it should be avoided otherwise. func (x *Int) Bits() []Word { + panic("todo big.Bits") } // SetBits provides raw (unchecked but fast) access to z by setting its @@ -100,17 +129,9 @@ func (x *Int) Bits() []Word { // SetBits is intended to support implementation of missing low-level Int // functionality outside this package; it should be avoided otherwise. func (z *Int) SetBits(abs []Word) *Int { + panic("todo big.SetBits") } -// Abs sets z to |x| (the absolute value of x) and returns z. -func (z *Int) Abs(x *Int) *Int { -} - -// Neg sets z to -x and returns z. -func (z *Int) Neg(x *Int) *Int { -} -*/ - // Add sets z to the sum x+y and returns z. func (z *Int) Add(x, y *Int) *Int { (*openssl.BIGNUM)(z).Add((*openssl.BIGNUM)(x), (*openssl.BIGNUM)(y)) @@ -123,31 +144,35 @@ func (z *Int) Sub(x, y *Int) *Int { return z } -/* // Mul sets z to the product x*y and returns z. func (z *Int) Mul(x, y *Int) *Int { + panic("todo big.Mul") } // MulRange sets z to the product of all integers // in the range [a, b] inclusively and returns z. // If a > b (empty range), the result is 1. func (z *Int) MulRange(a, b int64) *Int { + panic("todo big.MulRange") } // Binomial sets z to the binomial coefficient C(n, k) and returns z. func (z *Int) Binomial(n, k int64) *Int { + panic("todo big.Binomial") } // Quo sets z to the quotient x/y for y != 0 and returns z. // If y == 0, a division-by-zero run-time panic occurs. // Quo implements truncated division (like Go); see QuoRem for more details. func (z *Int) Quo(x, y *Int) *Int { + panic("todo big.Quo") } // Rem sets z to the remainder x%y for y != 0 and returns z. // If y == 0, a division-by-zero run-time panic occurs. // Rem implements truncated modulus (like Go); see QuoRem for more details. func (z *Int) Rem(x, y *Int) *Int { + panic("todo big.Rem") } // QuoRem sets z to the quotient x/y and r to the remainder x%y @@ -162,18 +187,21 @@ func (z *Int) Rem(x, y *Int) *Int { // (See Daan Leijen, “Division and Modulus for Computer Scientists”.) // See DivMod for Euclidean division and modulus (unlike Go). func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) { + panic("todo big.QuoRem") } // Div sets z to the quotient x/y for y != 0 and returns z. // If y == 0, a division-by-zero run-time panic occurs. // Div implements Euclidean division (unlike Go); see DivMod for more details. func (z *Int) Div(x, y *Int) *Int { + panic("todo big.Div") } // Mod sets z to the modulus x%y for y != 0 and returns z. // If y == 0, a division-by-zero run-time panic occurs. // Mod implements Euclidean modulus (unlike Go); see DivMod for more details. func (z *Int) Mod(x, y *Int) *Int { + panic("todo big.Mod") } // DivMod sets z to the quotient x div y and m to the modulus x mod y @@ -191,8 +219,8 @@ func (z *Int) Mod(x, y *Int) *Int { // ACM press.) // See QuoRem for T-division and modulus (like Go). func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) { + panic("big.DivMod") } -*/ // Cmp compares x and y and returns: // @@ -212,29 +240,35 @@ func (x *Int) CmpAbs(y *Int) int { return int((*openssl.BIGNUM)(x).Ucmp((*openssl.BIGNUM)(y))) } -/* // Int64 returns the int64 representation of x. // If x cannot be represented in an int64, the result is undefined. func (x *Int) Int64() int64 { + panic("todo big.Int64") } // Uint64 returns the uint64 representation of x. // If x cannot be represented in a uint64, the result is undefined. func (x *Int) Uint64() uint64 { + panic("todo big.Uint64") } // IsInt64 reports whether x can be represented as an int64. func (x *Int) IsInt64() bool { + panic("todo big.IsInt64") } // IsUint64 reports whether x can be represented as a uint64. func (x *Int) IsUint64() bool { + panic("todo big.IsUint64") } // Float64 returns the float64 value nearest x, // and an indication of any rounding that occurred. // TODO(xsw): -// func (x *Int) Float64() (float64, Accuracy) +/* +func (x *Int) Float64() (float64, Accuracy) { + panic("todo big.Float64") +}*/ // SetString sets z to the value of s, interpreted in the given base, // and returns z and a boolean indicating success. The entire string @@ -259,17 +293,20 @@ func (x *Int) IsUint64() bool { // are no other errors. If base != 0, underscores are not recognized // and act like any other character that is not a valid digit. func (z *Int) SetString(s string, base int) (*Int, bool) { + panic("todo big.SetString") } // SetBytes interprets buf as the bytes of a big-endian unsigned // integer, sets z to that value, and returns z. func (z *Int) SetBytes(buf []byte) *Int { + panic("todo big.SetBytes") } // Bytes returns the absolute value of x as a big-endian byte slice. // // To use a fixed length slice, or a preallocated one, use FillBytes. func (x *Int) Bytes() []byte { + panic("todo big.Bytes") } // FillBytes sets buf to the absolute value of x, storing it as a zero-extended @@ -277,18 +314,20 @@ func (x *Int) Bytes() []byte { // // If the absolute value of x doesn't fit in buf, FillBytes will panic. func (x *Int) FillBytes(buf []byte) []byte { + panic("todo big.FillBytes") } // BitLen returns the length of the absolute value of x in bits. // The bit length of 0 is 0. func (x *Int) BitLen() int { + panic("todo big.BitLen") } // TrailingZeroBits returns the number of consecutive least significant zero // bits of |x|. func (x *Int) TrailingZeroBits() uint { + panic("todo big.TrailingZeroBits") } -*/ // Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z. // If m == nil or m == 0, z = x**y unless y <= 0 then z = 1. If m != 0, y < 0, @@ -308,7 +347,6 @@ func (z *Int) Exp(x, y, m *Int) *Int { return z } -/* // GCD sets z to the greatest common divisor of a and b and returns z. // If x or y are not nil, GCD sets their value such that z = a*x + b*y. // @@ -321,6 +359,7 @@ func (z *Int) Exp(x, y, m *Int) *Int { // // If a != 0 and b == 0, GCD sets z = |a|, x = sign(a) * 1, y = 0. func (z *Int) GCD(x, y, a, b *Int) *Int { + panic("todo big.GCD") } // Rand sets z to a pseudo-random number in [0, n) and returns z. @@ -328,6 +367,7 @@ func (z *Int) GCD(x, y, a, b *Int) *Int { // As this uses the math/rand package, it must not be used for // security-sensitive work. Use crypto/rand.Int instead. func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int { + panic("todo big.Rand") } // ModInverse sets z to the multiplicative inverse of g in the ring ℤ/nℤ @@ -335,11 +375,13 @@ func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int { // inverse in the ring ℤ/nℤ. In this case, z is unchanged and the return value // is nil. If n == 0, a division-by-zero run-time panic occurs. func (z *Int) ModInverse(g, n *Int) *Int { + panic("todo big.ModInverse") } // Jacobi returns the Jacobi symbol (x/y), either +1, -1, or 0. // The y argument must be an odd integer. func Jacobi(x, y *Int) int { + panic("todo big.Jacobi") } // ModSqrt sets z to a square root of x mod p if such a square root exists, and @@ -347,19 +389,29 @@ func Jacobi(x, y *Int) int { // ModSqrt leaves z unchanged and returns nil. This function panics if p is // not an odd integer, its behavior is undefined if p is odd but not prime. func (z *Int) ModSqrt(x, p *Int) *Int { + panic("todo big.ModSqrt") } // Lsh sets z = x << n and returns z. func (z *Int) Lsh(x *Int, n uint) *Int { + a := (*openssl.BIGNUM)(z) + b := (*openssl.BIGNUM)(x) + a.Lshift(b, c.Int(n)) + return z } // Rsh sets z = x >> n and returns z. func (z *Int) Rsh(x *Int, n uint) *Int { + a := (*openssl.BIGNUM)(z) + b := (*openssl.BIGNUM)(x) + a.Rshift(b, c.Int(n)) + return z } // Bit returns the value of the i'th bit of x. That is, it // returns (x>>i)&1. The bit index i must be >= 0. func (x *Int) Bit(i int) uint { + panic("todo big.Bit") } // SetBit sets z to x, with x's i'th bit set to b (0 or 1). @@ -367,32 +419,38 @@ func (x *Int) Bit(i int) uint { // if b is 0 SetBit sets z = x &^ (1 << i). If b is not 0 or 1, // SetBit will panic. func (z *Int) SetBit(x *Int, i int, b uint) *Int { + panic("todo big.SetBit") } // And sets z = x & y and returns z. func (z *Int) And(x, y *Int) *Int { + panic("todo big.And") } // AndNot sets z = x &^ y and returns z. func (z *Int) AndNot(x, y *Int) *Int { + panic("todo big.AndNot") } // Or sets z = x | y and returns z. func (z *Int) Or(x, y *Int) *Int { + panic("todo big.Or") } // Xor sets z = x ^ y and returns z. func (z *Int) Xor(x, y *Int) *Int { + panic("todo big.Xor") } // Not sets z = ^x and returns z. func (z *Int) Not(x *Int) *Int { + panic("todo big.Not") } // Sqrt sets z to ⌊√x⌋, the largest integer such that z² ≤ x, and returns z. // It panics if x is negative. func (z *Int) Sqrt(x *Int) *Int { + panic("todo big.Sqrt") } -*/ // -----------------------------------------------------------------------------