func sieveInterval(n *big.Int) (min, max *big.Int) { lnn := float64(n.BitLen()) * math.Log(2) if lnn < 1.0 { /* if this is not done. if n is 1 everything explodes sqrt(<0) = NaN */ lnn = 1.0 } lnlnn := math.Log(lnn) exp := int64(math.Ceil(math.Sqrt(lnn*lnlnn) * math.Log2(math.E))) L := big.NewInt(0) L.Exp(misc.Two, big.NewInt(exp), nil) // magic parameter (wikipedia) sqrtN := misc.SquareRootCeil(n) sieveMin := big.NewInt(0) sieveMin.Sub(sqrtN, L) sieveMax := big.NewInt(0) sieveMax.Add(sqrtN, L) return sieveMin, sieveMax }
func findXandY(n *big.Int, cis, dis []*big.Int, exponents [][]int) (*big.Int, *big.Int) { ls := linearSystemFromExponents(exponents) ls.GaussianElimination(ls) ls = ls.EliminateEmptyRows() ls = ls.Transpose() usedCombinations := ls.MakeEmptyRows() if len(usedCombinations) == 0 { return nil, nil } aAndBSquaredList := []AandBSquared{} for _, indexSet := range usedCombinations { a := big.NewInt(1) bb := big.NewInt(1) for _, i := range indexSet { a.Mul(a, cis[i]) bb.Mul(bb, dis[i]) } aAndBSquaredList = append(aAndBSquaredList, AandBSquared{a, bb}) } x := big.NewInt(0) y := big.NewInt(0) xTimesY := big.NewInt(0) multiplicity := big.NewInt(0) testMod := big.NewInt(0) gcd := big.NewInt(0) abbChannel := make(chan AandBSquared, 100000) doneChannel := make(chan bool) cancelChannel := make(chan bool, 1) var abb AandBSquared go createPowerSetRecursively(0, AandBSquared{big.NewInt(1), big.NewInt(1)}, aAndBSquaredList, abbChannel, cancelChannel, doneChannel) numberOfIndexSetsToGo := -1 for attempts := 0; ; /*attempts < 100*/ attempts += 1 { if numberOfIndexSetsToGo == 0 { break } select { case <-doneChannel: numberOfIndexSetsToGo = len(abbChannel) continue case abb = <-abbChannel: if numberOfIndexSetsToGo > -1 { numberOfIndexSetsToGo -= 1 } } x.SetInt64(0) y.SetInt64(0) abb.b = misc.SquareRootCeil(abb.b) x.Add(abb.a, abb.b) x.Mod(x, n) y.Sub(abb.a, abb.b) y.Mod(y, n) if x.Cmp(misc.Zero) == 0 || x.Cmp(misc.One) == 0 || y.Cmp(misc.Zero) == 0 || y.Cmp(misc.One) == 0 { /* discard trivial solutions */ continue } xTimesY.Mul(x, y) multiplicity.DivMod(xTimesY, n, testMod) if testMod.Cmp(misc.Zero) != 0 { continue } if multiplicity.Cmp(misc.One) == 1 { gcd.GCD(nil, nil, x, multiplicity) if x.Cmp(gcd) != 0 { x.Div(x, gcd) } multiplicity.Div(multiplicity, gcd) gcd.GCD(nil, nil, y, multiplicity) if y.Cmp(gcd) != 0 { y.Div(y, gcd) } } cancelChannel <- true return x, y } cancelChannel <- true return nil, nil }