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 }