func (ot *PoolSameUnit) ConnectPools(send, recv *etensor.Shape, same bool) (sendn, recvn *etensor.Int32, cons *etensor.Bits) {
	sendn, recvn, cons = NewTensors(send, recv)
	sNtot := send.Len()
	sNp := send.Dim(0) * send.Dim(1)
	rNp := recv.Dim(0) * recv.Dim(1)
	sNu := send.Dim(2) * send.Dim(3)
	rNu := recv.Dim(2) * recv.Dim(3)
	rnv := recvn.Values
	snv := sendn.Values
	for rpi := 0; rpi < rNp; rpi++ {
		for rui := 0; rui < rNu; rui++ {
			if rui >= sNu {
				break
			}
			ri := rpi*rNu + rui
			for spi := 0; spi < sNp; spi++ {
				if same && !ot.SelfCon && spi == rpi {
					continue
				}
				si := spi*sNu + rui
				off := ri*sNtot + si
				cons.Values.Set(off, true)
				rnv[ri]++
				snv[si]++
			}
		}
	}
	return
}
ConnectPools is when both recv and send have pools
package prjn
import (
	"github.com/emer/etable/etensor"
)
type PoolSameUnit struct {
	SelfCon bool `desc:"if true, and connecting layer to itself (self projection), then make a self-connection from unit to itself"`
}
func NewPoolSameUnit() *PoolSameUnit {
	return &PoolSameUnit{}
}
func (ot *PoolSameUnit) Name() string {
	return "PoolSameUnit"
}
func (ot *PoolSameUnit) Connect(send, recv *etensor.Shape, same bool) (sendn, recvn *etensor.Int32, cons *etensor.Bits) {
	switch {
	case send.NumDims() == 4 && recv.NumDims() == 4:
		return ot.ConnectPools(send, recv, same)
	case send.NumDims() == 2 && recv.NumDims() == 4:
		return ot.ConnectRecvPool(send, recv, same)
	case send.NumDims() == 4 && recv.NumDims() == 2:
		return ot.ConnectSendPool(send, recv, same)
	case send.NumDims() == 2 && recv.NumDims() == 2:
		return ot.ConnectOneToOne(send, recv, same)
	}
	return
}