123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- package tools
- import (
- "context"
- "errors"
- "math/big"
- "math/rand"
- "time"
- )
- var (
- rnd = rand.New(rand.NewSource(time.Now().UnixNano())) // Генератор случайных чисел
- intZero = big.NewInt(0)
- intMax, _ = new(big.Int).SetString("9223372036854775807", 10)
- )
- func intCopy(val *big.Int) (res *big.Int) {
- if val != nil {
- res = new(big.Int).Set(val)
- }
- return
- }
- // Возвращает число или 0 при пустом указателе
- func mustBigInt(val *big.Int) (res *big.Int) {
- res = val
- if res == nil {
- res = big.NewInt(0)
- }
- return res
- }
- func IsPrime(val *big.Int) bool {
- return val.ProbablyPrime(100)
- }
- func SearchP(min *big.Int, ctx context.Context) (p *big.Int, g *big.Int, err error) {
- ch := make(chan struct{})
- go func() {
- defer func() {
- close(ch)
- }()
- p = intCopy(min)
- var check bool
- for {
- select {
- case <-ctx.Done():
- err = errors.New("Поиск поля и первообразного корня - время вышло")
- return
- default:
- if g, check = CheckP(p); check {
- ch <- struct{}{}
- return
- }
- p = Add64(p, 1)
- }
- }
- }()
- <-ch
- return
- }
- func CheckP(val *big.Int) (res *big.Int, check bool) {
- if IsPrime(val) {
- //log.Println("PRIME", val, Div64(Sub64(val, 1), 2))
- res = Div64(Sub64(val, 1), 2)
- check = IsPrime(res)
- }
- return
- }
- func SearchPrime(val *big.Int) *big.Int {
- rVal := new(big.Int).Set(val)
- //log.Println(rVal)
- for {
- if rVal.ProbablyPrime(100) {
- break
- }
- rVal.Add(rVal, big.NewInt(1))
- //log.Println(rVal)
- }
- return rVal
- }
- func Random(min, max *big.Int) *big.Int {
- if min == nil {
- min = intZero
- }
- if max == nil {
- max = intMax
- }
- res := new(big.Int).Rand(rnd, max)
- for res.Cmp(min) == -1 {
- res = new(big.Int).Rand(rnd, max)
- }
- return res
- }
- // Проверка кривой на сингулярность (4a³ + 27b² = 0)
- func IsCurveSingular(a, b *big.Int) bool {
- l := Mul64(Exp64(a, 3), 4)
- r := Mul64(Exp64(b, 2), 27)
- return l.Add(l, r).Cmp(intZero) == 0
- }
- func CurveRandomParams(max *big.Int) (a, b, p *big.Int) {
- for {
- a, b = Random(intZero, max), Random(intZero, max)
- if !IsCurveSingular(a, b) {
- break
- }
- }
- p = SearchPrime(Random(intZero, max))
- return
- }
|