func (ur *UnifRnd) ConnectRecip(send, recv *etensor.Shape, same bool) (sendn, recvn *etensor.Int32, cons *etensor.Bits) {
	sendn, recvn, cons = NewTensors(send, recv)
	slen := recv.Len()  
	rlen := send.Len()
	slenR := send.Len()  
	noself := same && !ur.SelfCon
	var nsend int
	if noself {
		nsend = int(math.Round(float64(ur.PCon) * float64(slen-1)))
	} else {
		nsend = int(math.Round(float64(ur.PCon) * float64(slen)))
	}
	rnv := sendn.Values  
	for i := range rnv {
		rnv[i] = int32(nsend)
	}
	if ur.RndSeed == 0 {
		ur.RndSeed = int64(rand.Uint64())
	}
	rand.Seed(ur.RndSeed)
	sordlen := slen
	if noself {
		sordlen--
	}
	sorder := rand.Perm(sordlen)
	slist := make([]int, nsend)
	for ri := 0; ri < rlen; ri++ {
		if noself {  
			ix := 0
			for j := 0; j < slen; j++ {
				if j != ri {
					sorder[ix] = j
					ix++
				}
			}
			erand.PermuteInts(sorder)
		}
		copy(slist, sorder)
		sort.Ints(slist)  
		for si := 0; si < nsend; si++ {
			off := slist[si]*slenR + ri
			cons.Values.Set(off, true)
		}
		erand.PermuteInts(sorder)
	}
	snv := recvn.Values  
	for si := range snv {
		nr := 0
		for ri := 0; ri < rlen; ri++ {  
			off := si*slenR + ri
			if cons.Values.Index(off) {
				nr++
			}
		}
		snv[si] = int32(nr)
	}
	return
}
ConnectRecip does reciprocal connectvity
package prjn
import (
	"math"
	"math/rand"
	"sort"
	"github.com/emer/emergent/erand"
	"github.com/emer/etable/etensor"
)
type UnifRnd struct {
	PCon    float32 `min:"0" max:"1" desc:"probability of connection (0-1)"`
	RndSeed int64   `view:"-" desc:"the current random seed"`
	SelfCon bool    `desc:"if true, and connecting layer to itself (self projection), then make a self-connection from unit to itself"`
	Recip   bool    `desc:"reciprocal connectivity: if true, switch the sending and receiving layers to create a symmetric top-down projection -- ESSENTIAL to use same RndSeed between two prjns to ensure symmetry"`
}
func NewUnifRnd() *UnifRnd {
	return &UnifRnd{PCon: 0.5}
}
func (ur *UnifRnd) Name() string {
	return "UnifRnd"
}
func (ur *UnifRnd) Connect(send, recv *etensor.Shape, same bool) (sendn, recvn *etensor.Int32, cons *etensor.Bits) {
	if ur.PCon >= 1 {
		return ur.ConnectFull(send, recv, same)
	}
	if ur.Recip {
		return ur.ConnectRecip(send, recv, same)
	}
	sendn, recvn, cons = NewTensors(send, recv)
	slen := send.Len()
	rlen := recv.Len()
	noself := same && !ur.SelfCon
	var nsend int
	if noself {
		nsend = int(math.Round(float64(ur.PCon) * float64(slen-1)))
	} else {
		nsend = int(math.Round(float64(ur.PCon) * float64(slen)))
	}
	rnv := recvn.Values
	for i := range rnv {
		rnv[i] = int32(nsend)
	}
	if ur.RndSeed == 0 {
		ur.RndSeed = int64(rand.Uint64())
	}
	rand.Seed(ur.RndSeed)
	sordlen := slen
	if noself {
		sordlen--
	}
	sorder := rand.Perm(sordlen)
	slist := make([]int, nsend)
	for ri := 0; ri < rlen; ri++ {
		if noself {  
			ix := 0
			for j := 0; j < slen; j++ {
				if j != ri {
					sorder[ix] = j
					ix++
				}
			}
			erand.PermuteInts(sorder)
		}
		copy(slist, sorder)
		sort.Ints(slist)  
		for si := 0; si < nsend; si++ {
			off := ri*slen + slist[si]
			cons.Values.Set(off, true)
		}
		erand.PermuteInts(sorder)
	}
	snv := sendn.Values
	for si := range snv {
		nr := 0
		for ri := 0; ri < rlen; ri++ {
			off := ri*slen + si
			if cons.Values.Index(off) {
				nr++
			}
		}
		snv[si] = int32(nr)
	}
	return
}