// For each input modulus 'x' and remainderTree parent 'y', compute z = (y%(x*x))/x; gcd(z, x) func lowmemRemainderTreeFinal(input, moduli chan *gmp.Int, output chan<- Collision) { defer close(output) tmp := new(gmp.Int) for y := range input { for i := 0; i < 2; i++ { modulus, ok := <-moduli if !ok { log.Print("Odd number of moduli? (should only see this once)") continue } tmp.Mul(modulus, modulus) tmp.Rem(y, tmp) tmp.Quo(tmp, modulus) if tmp.GCD(nil, nil, tmp, modulus).BitLen() != 1 { q := new(gmp.Int).Quo(modulus, tmp) output <- Collision{ Modulus: modulus, P: tmp, Q: q, } tmp = new(gmp.Int) } } y.Clear() } }
// For each productTree node 'x', and remainderTree parent 'y', compute y%(x*x) func remainderTreeLevel(tree [][]*gmp.Int, level int, wg *sync.WaitGroup, start, step int) { prevLevel := tree[level+1] thisLevel := tree[level] tmp := new(gmp.Int) for i := start; i < len(thisLevel); i += step { x := thisLevel[i] y := prevLevel[i/2] tmp.Mul(x, x) x.Rem(y, tmp) } wg.Done() }
// For each input modulus 'x' and remainderTree parent 'y', compute z = (y%(x*x))/x; gcd(z, x) func remainderTreeFinal(lastLevel, moduli []*gmp.Int, output chan<- Collision, wg *sync.WaitGroup, start, step int) { tmp := new(gmp.Int) for i := start; i < len(moduli); i += step { modulus := moduli[i] y := lastLevel[i/2] tmp.Mul(modulus, modulus) tmp.Rem(y, tmp) tmp.Quo(tmp, modulus) if tmp.GCD(nil, nil, tmp, modulus).BitLen() != 1 { q := new(gmp.Int).Quo(modulus, tmp) output <- Collision{ Modulus: modulus, P: tmp, Q: q, } tmp = new(gmp.Int) } } wg.Done() }
// For each productTree node 'x', and remainderTree parent 'y', compute y%(x*x) func lowmemRemainderTreeLevel(input chan *gmp.Int, productTree []fileChannels, finalOutput chan<- Collision) { tmp := new(gmp.Int) ch := productTree[len(productTree)-1] productTree = productTree[:len(productTree)-1] // We close the fileWriteChannel here so it kicks off reading now, instead of starting too early products := ch.readChan output := make(chan *gmp.Int, 2) defer close(output) if len(productTree) == 0 { ch.StartProducing() lowmemRemainderTreeFinal(input, products, finalOutput) return } else { go lowmemRemainderTreeLevel(output, productTree, finalOutput) } for y := range input { ch.StartProducing() x, ok := <-products if !ok { log.Panicf("Expecting more products") } tmp.Mul(x, x) x.Rem(y, tmp) output <- x x, ok = <-products if ok { tmp.Mul(x, x) x.Rem(y, tmp) output <- x } y.Clear() } }