// 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()
	}
}
Exemple #2
0
// 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()
}
Exemple #3
0
// 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()
	}
}