github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/swarm/pot/pot.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package pot see doc.go
    18  package pot
    19  
    20  import (
    21  	"fmt"
    22  	"sync"
    23  )
    24  
    25  const (
    26  	maxkeylen = 256
    27  )
    28  
    29  // Pot is the node type (same for root, branching node and leaf)
    30  type Pot struct {
    31  	pin  Val
    32  	bins []*Pot
    33  	size int
    34  	po   int
    35  }
    36  
    37  // Val is the element type for Pots
    38  type Val interface{}
    39  
    40  // Pof is the proximity order comparison operator function
    41  type Pof func(Val, Val, int) (int, bool)
    42  
    43  // NewPot constructor. Requires a value of type Val to pin
    44  // and po to point to a span in the Val key
    45  // The pinned item counts towards the size
    46  func NewPot(v Val, po int) *Pot {
    47  	var size int
    48  	if v != nil {
    49  		size++
    50  	}
    51  	return &Pot{
    52  		pin:  v,
    53  		po:   po,
    54  		size: size,
    55  	}
    56  }
    57  
    58  // Pin returns the pinned element (key) of the Pot
    59  func (t *Pot) Pin() Val {
    60  	return t.pin
    61  }
    62  
    63  // Size returns the number of values in the Pot
    64  func (t *Pot) Size() int {
    65  	if t == nil {
    66  		return 0
    67  	}
    68  	return t.size
    69  }
    70  
    71  // Add inserts a new value into the Pot and
    72  // returns the proximity order of v and a boolean
    73  // indicating if the item was found
    74  // Add called on (t, v) returns a new Pot that contains all the elements of t
    75  // plus the value v, using the applicative add
    76  // the second return value is the proximity order of the inserted element
    77  // the third is boolean indicating if the item was found
    78  func Add(t *Pot, val Val, pof Pof) (*Pot, int, bool) {
    79  	return add(t, val, pof)
    80  }
    81  
    82  func (t *Pot) clone() *Pot {
    83  	return &Pot{
    84  		pin:  t.pin,
    85  		size: t.size,
    86  		po:   t.po,
    87  		bins: t.bins,
    88  	}
    89  }
    90  
    91  func add(t *Pot, val Val, pof Pof) (*Pot, int, bool) {
    92  	var r *Pot
    93  	if t == nil || t.pin == nil {
    94  		r = t.clone()
    95  		r.pin = val
    96  		r.size++
    97  		return r, 0, false
    98  	}
    99  	po, found := pof(t.pin, val, t.po)
   100  	if found {
   101  		r = t.clone()
   102  		r.pin = val
   103  		return r, po, true
   104  	}
   105  
   106  	var p *Pot
   107  	var i, j int
   108  	size := t.size
   109  	for i < len(t.bins) {
   110  		n := t.bins[i]
   111  		if n.po == po {
   112  			p, _, found = add(n, val, pof)
   113  			if !found {
   114  				size++
   115  			}
   116  			j++
   117  			break
   118  		}
   119  		if n.po > po {
   120  			break
   121  		}
   122  		i++
   123  		j++
   124  	}
   125  	if p == nil {
   126  		size++
   127  		p = &Pot{
   128  			pin:  val,
   129  			size: 1,
   130  			po:   po,
   131  		}
   132  	}
   133  
   134  	bins := append([]*Pot{}, t.bins[:i]...)
   135  	bins = append(bins, p)
   136  	bins = append(bins, t.bins[j:]...)
   137  	r = &Pot{
   138  		pin:  t.pin,
   139  		size: size,
   140  		po:   t.po,
   141  		bins: bins,
   142  	}
   143  
   144  	return r, po, found
   145  }
   146  
   147  // Remove called on (v) deletes v from the Pot and returns
   148  // the proximity order of v and a boolean value indicating
   149  // if the value was found
   150  // Remove called on (t, v) returns a new Pot that contains all the elements of t
   151  // minus the value v, using the applicative remove
   152  // the second return value is the proximity order of the inserted element
   153  // the third is boolean indicating if the item was found
   154  func Remove(t *Pot, v Val, pof Pof) (*Pot, int, bool) {
   155  	return remove(t, v, pof)
   156  }
   157  
   158  func remove(t *Pot, val Val, pof Pof) (r *Pot, po int, found bool) {
   159  	size := t.size
   160  	po, found = pof(t.pin, val, t.po)
   161  	if found {
   162  		size--
   163  		if size == 0 {
   164  			r = &Pot{
   165  				po: t.po,
   166  			}
   167  			return r, po, true
   168  		}
   169  		i := len(t.bins) - 1
   170  		last := t.bins[i]
   171  		r = &Pot{
   172  			pin:  last.pin,
   173  			bins: append(t.bins[:i], last.bins...),
   174  			size: size,
   175  			po:   t.po,
   176  		}
   177  		return r, t.po, true
   178  	}
   179  
   180  	var p *Pot
   181  	var i, j int
   182  	for i < len(t.bins) {
   183  		n := t.bins[i]
   184  		if n.po == po {
   185  			p, po, found = remove(n, val, pof)
   186  			if found {
   187  				size--
   188  			}
   189  			j++
   190  			break
   191  		}
   192  		if n.po > po {
   193  			return t, po, false
   194  		}
   195  		i++
   196  		j++
   197  	}
   198  	bins := t.bins[:i]
   199  	if p != nil && p.pin != nil {
   200  		bins = append(bins, p)
   201  	}
   202  	bins = append(bins, t.bins[j:]...)
   203  	r = &Pot{
   204  		pin:  val,
   205  		size: size,
   206  		po:   t.po,
   207  		bins: bins,
   208  	}
   209  	return r, po, found
   210  }
   211  
   212  // Swap called on (k, f) looks up the item at k
   213  // and applies the function f to the value v at k or to nil if the item is not found
   214  // if f(v) returns nil, the element is removed
   215  // if f(v) returns v' <> v then v' is inserted into the Pot
   216  // if (v) == v the Pot is not changed
   217  // it panics if Pof(f(v), k) show that v' and v are not key-equal
   218  func Swap(t *Pot, k Val, pof Pof, f func(v Val) Val) (r *Pot, po int, found bool, change bool) {
   219  	var val Val
   220  	if t.pin == nil {
   221  		val = f(nil)
   222  		if val == nil {
   223  			return nil, 0, false, false
   224  		}
   225  		return NewPot(val, t.po), 0, false, true
   226  	}
   227  	size := t.size
   228  	po, found = pof(k, t.pin, t.po)
   229  	if found {
   230  		val = f(t.pin)
   231  		// remove element
   232  		if val == nil {
   233  			size--
   234  			if size == 0 {
   235  				r = &Pot{
   236  					po: t.po,
   237  				}
   238  				// return empty pot
   239  				return r, po, true, true
   240  			}
   241  			// actually remove pin, by merging last bin
   242  			i := len(t.bins) - 1
   243  			last := t.bins[i]
   244  			r = &Pot{
   245  				pin:  last.pin,
   246  				bins: append(t.bins[:i], last.bins...),
   247  				size: size,
   248  				po:   t.po,
   249  			}
   250  			return r, po, true, true
   251  		}
   252  		// element found but no change
   253  		if val == t.pin {
   254  			return t, po, true, false
   255  		}
   256  		// actually modify the pinned element, but no change in structure
   257  		r = t.clone()
   258  		r.pin = val
   259  		return r, po, true, true
   260  	}
   261  
   262  	// recursive step
   263  	var p *Pot
   264  	n, i := t.getPos(po)
   265  	if n != nil {
   266  		p, po, found, change = Swap(n, k, pof, f)
   267  		// recursive no change
   268  		if !change {
   269  			return t, po, found, false
   270  		}
   271  		// recursive change
   272  		bins := append([]*Pot{}, t.bins[:i]...)
   273  		if p.size == 0 {
   274  			size--
   275  		} else {
   276  			size += p.size - n.size
   277  			bins = append(bins, p)
   278  		}
   279  		i++
   280  		if i < len(t.bins) {
   281  			bins = append(bins, t.bins[i:]...)
   282  		}
   283  		r = t.clone()
   284  		r.bins = bins
   285  		r.size = size
   286  		return r, po, found, true
   287  	}
   288  	// key does not exist
   289  	val = f(nil)
   290  	if val == nil {
   291  		// and it should not be created
   292  		return t, po, false, false
   293  	}
   294  	// otherwise check val if equal to k
   295  	if _, eq := pof(val, k, po); !eq {
   296  		panic("invalid value")
   297  	}
   298  	///
   299  	size++
   300  	p = &Pot{
   301  		pin:  val,
   302  		size: 1,
   303  		po:   po,
   304  	}
   305  
   306  	bins := append([]*Pot{}, t.bins[:i]...)
   307  	bins = append(bins, p)
   308  	if i < len(t.bins) {
   309  		bins = append(bins, t.bins[i:]...)
   310  	}
   311  	r = t.clone()
   312  	r.bins = bins
   313  	r.size = size
   314  	return r, po, found, true
   315  }
   316  
   317  // Union called on (t0, t1, pof) returns the union of t0 and t1
   318  // calculates the union using the applicative union
   319  // the second return value is the number of common elements
   320  func Union(t0, t1 *Pot, pof Pof) (*Pot, int) {
   321  	return union(t0, t1, pof)
   322  }
   323  
   324  func union(t0, t1 *Pot, pof Pof) (*Pot, int) {
   325  	if t0 == nil || t0.size == 0 {
   326  		return t1, 0
   327  	}
   328  	if t1 == nil || t1.size == 0 {
   329  		return t0, 0
   330  	}
   331  	var pin Val
   332  	var bins []*Pot
   333  	var mis []int
   334  	wg := &sync.WaitGroup{}
   335  	wg.Add(1)
   336  	pin0 := t0.pin
   337  	pin1 := t1.pin
   338  	bins0 := t0.bins
   339  	bins1 := t1.bins
   340  	var i0, i1 int
   341  	var common int
   342  
   343  	po, eq := pof(pin0, pin1, 0)
   344  
   345  	for {
   346  		l0 := len(bins0)
   347  		l1 := len(bins1)
   348  		var n0, n1 *Pot
   349  		var p0, p1 int
   350  		var a0, a1 bool
   351  
   352  		for {
   353  
   354  			if !a0 && i0 < l0 && bins0[i0] != nil && bins0[i0].po <= po {
   355  				n0 = bins0[i0]
   356  				p0 = n0.po
   357  				a0 = p0 == po
   358  			} else {
   359  				a0 = true
   360  			}
   361  
   362  			if !a1 && i1 < l1 && bins1[i1] != nil && bins1[i1].po <= po {
   363  				n1 = bins1[i1]
   364  				p1 = n1.po
   365  				a1 = p1 == po
   366  			} else {
   367  				a1 = true
   368  			}
   369  			if a0 && a1 {
   370  				break
   371  			}
   372  
   373  			switch {
   374  			case (p0 < p1 || a1) && !a0:
   375  				bins = append(bins, n0)
   376  				i0++
   377  				n0 = nil
   378  			case (p1 < p0 || a0) && !a1:
   379  				bins = append(bins, n1)
   380  				i1++
   381  				n1 = nil
   382  			case p1 < po:
   383  				bl := len(bins)
   384  				bins = append(bins, nil)
   385  				ml := len(mis)
   386  				mis = append(mis, 0)
   387  				// wg.Add(1)
   388  				// go func(b, m int, m0, m1 *Pot) {
   389  				// 	defer wg.Done()
   390  				// bins[b], mis[m] = union(m0, m1, pof)
   391  				// }(bl, ml, n0, n1)
   392  				bins[bl], mis[ml] = union(n0, n1, pof)
   393  				i0++
   394  				i1++
   395  				n0 = nil
   396  				n1 = nil
   397  			}
   398  		}
   399  
   400  		if eq {
   401  			common++
   402  			pin = pin1
   403  			break
   404  		}
   405  
   406  		i := i0
   407  		if len(bins0) > i && bins0[i].po == po {
   408  			i++
   409  		}
   410  		var size0 int
   411  		for _, n := range bins0[i:] {
   412  			size0 += n.size
   413  		}
   414  		np := &Pot{
   415  			pin:  pin0,
   416  			bins: bins0[i:],
   417  			size: size0 + 1,
   418  			po:   po,
   419  		}
   420  
   421  		bins2 := []*Pot{np}
   422  		if n0 == nil {
   423  			pin0 = pin1
   424  			po = maxkeylen + 1
   425  			eq = true
   426  			common--
   427  
   428  		} else {
   429  			bins2 = append(bins2, n0.bins...)
   430  			pin0 = pin1
   431  			pin1 = n0.pin
   432  			po, eq = pof(pin0, pin1, n0.po)
   433  
   434  		}
   435  		bins0 = bins1
   436  		bins1 = bins2
   437  		i0 = i1
   438  		i1 = 0
   439  
   440  	}
   441  
   442  	wg.Done()
   443  	wg.Wait()
   444  	for _, c := range mis {
   445  		common += c
   446  	}
   447  	n := &Pot{
   448  		pin:  pin,
   449  		bins: bins,
   450  		size: t0.size + t1.size - common,
   451  		po:   t0.po,
   452  	}
   453  	return n, common
   454  }
   455  
   456  // Each called with (f) is a synchronous iterator over the bins of a node
   457  // respecting an ordering
   458  // proximity > pinnedness
   459  func (t *Pot) Each(f func(Val, int) bool) bool {
   460  	return t.each(f)
   461  }
   462  
   463  func (t *Pot) each(f func(Val, int) bool) bool {
   464  	var next bool
   465  	for _, n := range t.bins {
   466  		if n == nil {
   467  			return true
   468  		}
   469  		next = n.each(f)
   470  		if !next {
   471  			return false
   472  		}
   473  	}
   474  	if t.size == 0 {
   475  		return false
   476  	}
   477  	return f(t.pin, t.po)
   478  }
   479  
   480  // EachFrom called with (f, start) is a synchronous iterator over the elements of a Pot
   481  // within the inclusive range starting from proximity order start
   482  // the function argument is passed the value and the proximity order wrt the root pin
   483  // it does NOT include the pinned item of the root
   484  // respecting an ordering
   485  // proximity > pinnedness
   486  // the iteration ends if the function return false or there are no more elements
   487  // end of a po range can be implemented since po is passed to the function
   488  func (t *Pot) EachFrom(f func(Val, int) bool, po int) bool {
   489  	return t.eachFrom(f, po)
   490  }
   491  
   492  func (t *Pot) eachFrom(f func(Val, int) bool, po int) bool {
   493  	var next bool
   494  	_, lim := t.getPos(po)
   495  	for i := lim; i < len(t.bins); i++ {
   496  		n := t.bins[i]
   497  		next = n.each(f)
   498  		if !next {
   499  			return false
   500  		}
   501  	}
   502  	return f(t.pin, t.po)
   503  }
   504  
   505  // EachBin iterates over bins of the pivot node and offers iterators to the caller on each
   506  // subtree passing the proximity order and the size
   507  // the iteration continues until the function's return value is false
   508  // or there are no more subtries
   509  func (t *Pot) EachBin(val Val, pof Pof, po int, f func(int, int, func(func(val Val, i int) bool) bool) bool) {
   510  	t.eachBin(val, pof, po, f)
   511  }
   512  
   513  func (t *Pot) eachBin(val Val, pof Pof, po int, f func(int, int, func(func(val Val, i int) bool) bool) bool) {
   514  	if t == nil || t.size == 0 {
   515  		return
   516  	}
   517  	spr, _ := pof(t.pin, val, t.po)
   518  	_, lim := t.getPos(spr)
   519  	var size int
   520  	var n *Pot
   521  	for i := 0; i < lim; i++ {
   522  		n = t.bins[i]
   523  		size += n.size
   524  		if n.po < po {
   525  			continue
   526  		}
   527  		if !f(n.po, n.size, n.each) {
   528  			return
   529  		}
   530  	}
   531  	if lim == len(t.bins) {
   532  		if spr >= po {
   533  			f(spr, 1, func(g func(Val, int) bool) bool {
   534  				return g(t.pin, spr)
   535  			})
   536  		}
   537  		return
   538  	}
   539  
   540  	n = t.bins[lim]
   541  
   542  	spo := spr
   543  	if n.po == spr {
   544  		spo++
   545  		size += n.size
   546  	}
   547  	if spr >= po {
   548  		if !f(spr, t.size-size, func(g func(Val, int) bool) bool {
   549  			return t.eachFrom(func(v Val, j int) bool {
   550  				return g(v, spr)
   551  			}, spo)
   552  		}) {
   553  			return
   554  		}
   555  	}
   556  	if n.po == spr {
   557  		n.eachBin(val, pof, po, f)
   558  	}
   559  
   560  }
   561  
   562  // EachNeighbour is a synchronous iterator over neighbours of any target val
   563  // the order of elements retrieved reflect proximity order to the target
   564  // TODO: add maximum proxbin to start range of iteration
   565  func (t *Pot) EachNeighbour(val Val, pof Pof, f func(Val, int) bool) bool {
   566  	return t.eachNeighbour(val, pof, f)
   567  }
   568  
   569  func (t *Pot) eachNeighbour(val Val, pof Pof, f func(Val, int) bool) bool {
   570  	if t == nil || t.size == 0 {
   571  		return false
   572  	}
   573  	var next bool
   574  	l := len(t.bins)
   575  	var n *Pot
   576  	ir := l
   577  	il := l
   578  	po, eq := pof(t.pin, val, t.po)
   579  	if !eq {
   580  		n, il = t.getPos(po)
   581  		if n != nil {
   582  			next = n.eachNeighbour(val, pof, f)
   583  			if !next {
   584  				return false
   585  			}
   586  			ir = il
   587  		} else {
   588  			ir = il - 1
   589  		}
   590  	}
   591  
   592  	next = f(t.pin, po)
   593  	if !next {
   594  		return false
   595  	}
   596  
   597  	for i := l - 1; i > ir; i-- {
   598  		next = t.bins[i].each(func(v Val, _ int) bool {
   599  			return f(v, po)
   600  		})
   601  		if !next {
   602  			return false
   603  		}
   604  	}
   605  
   606  	for i := il - 1; i >= 0; i-- {
   607  		n := t.bins[i]
   608  		next = n.each(func(v Val, _ int) bool {
   609  			return f(v, n.po)
   610  		})
   611  		if !next {
   612  			return false
   613  		}
   614  	}
   615  	return true
   616  }
   617  
   618  // EachNeighbourAsync called on (val, max, maxPos, f, wait) is an asynchronous iterator
   619  // over elements not closer than maxPos wrt val.
   620  // val does not need to be match an element of the Pot, but if it does, and
   621  // maxPos is keylength than it is included in the iteration
   622  // Calls to f are parallelised, the order of calls is undefined.
   623  // proximity order is respected in that there is no element in the Pot that
   624  // is not visited if a closer node is visited.
   625  // The iteration is finished when max number of nearest nodes is visited
   626  // or if the entire there are no nodes not closer than maxPos that is not visited
   627  // if wait is true, the iterator returns only if all calls to f are finished
   628  // TODO: implement minPos for proper prox range iteration
   629  func (t *Pot) EachNeighbourAsync(val Val, pof Pof, max int, maxPos int, f func(Val, int), wait bool) {
   630  	if max > t.size {
   631  		max = t.size
   632  	}
   633  	var wg *sync.WaitGroup
   634  	if wait {
   635  		wg = &sync.WaitGroup{}
   636  	}
   637  	t.eachNeighbourAsync(val, pof, max, maxPos, f, wg)
   638  	if wait {
   639  		wg.Wait()
   640  	}
   641  }
   642  
   643  func (t *Pot) eachNeighbourAsync(val Val, pof Pof, max int, maxPos int, f func(Val, int), wg *sync.WaitGroup) (extra int) {
   644  	l := len(t.bins)
   645  
   646  	po, eq := pof(t.pin, val, t.po)
   647  
   648  	// if po is too close, set the pivot branch (pom) to maxPos
   649  	pom := po
   650  	if pom > maxPos {
   651  		pom = maxPos
   652  	}
   653  	n, il := t.getPos(pom)
   654  	ir := il
   655  	// if pivot branch exists and po is not too close, iterate on the pivot branch
   656  	if pom == po {
   657  		if n != nil {
   658  
   659  			m := n.size
   660  			if max < m {
   661  				m = max
   662  			}
   663  			max -= m
   664  
   665  			extra = n.eachNeighbourAsync(val, pof, m, maxPos, f, wg)
   666  
   667  		} else {
   668  			if !eq {
   669  				ir--
   670  			}
   671  		}
   672  	} else {
   673  		extra++
   674  		max--
   675  		if n != nil {
   676  			il++
   677  		}
   678  		// before checking max, add up the extra elements
   679  		// on the close branches that are skipped (if po is too close)
   680  		for i := l - 1; i >= il; i-- {
   681  			s := t.bins[i]
   682  			m := s.size
   683  			if max < m {
   684  				m = max
   685  			}
   686  			max -= m
   687  			extra += m
   688  		}
   689  	}
   690  
   691  	var m int
   692  	if pom == po {
   693  
   694  		m, max, extra = need(1, max, extra)
   695  		if m <= 0 {
   696  			return
   697  		}
   698  
   699  		if wg != nil {
   700  			wg.Add(1)
   701  		}
   702  		go func() {
   703  			if wg != nil {
   704  				defer wg.Done()
   705  			}
   706  			f(t.pin, po)
   707  		}()
   708  
   709  		// otherwise iterats
   710  		for i := l - 1; i > ir; i-- {
   711  			n := t.bins[i]
   712  
   713  			m, max, extra = need(n.size, max, extra)
   714  			if m <= 0 {
   715  				return
   716  			}
   717  
   718  			if wg != nil {
   719  				wg.Add(m)
   720  			}
   721  			go func(pn *Pot, pm int) {
   722  				pn.each(func(v Val, _ int) bool {
   723  					if wg != nil {
   724  						defer wg.Done()
   725  					}
   726  					f(v, po)
   727  					pm--
   728  					return pm > 0
   729  				})
   730  			}(n, m)
   731  
   732  		}
   733  	}
   734  
   735  	// iterate branches that are farther tham pom with their own po
   736  	for i := il - 1; i >= 0; i-- {
   737  		n := t.bins[i]
   738  		// the first time max is less than the size of the entire branch
   739  		// wait for the pivot thread to release extra elements
   740  		m, max, extra = need(n.size, max, extra)
   741  		if m <= 0 {
   742  			return
   743  		}
   744  
   745  		if wg != nil {
   746  			wg.Add(m)
   747  		}
   748  		go func(pn *Pot, pm int) {
   749  			pn.each(func(v Val, _ int) bool {
   750  				if wg != nil {
   751  					defer wg.Done()
   752  				}
   753  				f(v, pn.po)
   754  				pm--
   755  				return pm > 0
   756  			})
   757  		}(n, m)
   758  
   759  	}
   760  	return max + extra
   761  }
   762  
   763  // getPos called on (n) returns the forking node at PO n and its index if it exists
   764  // otherwise nil
   765  // caller is supposed to hold the lock
   766  func (t *Pot) getPos(po int) (n *Pot, i int) {
   767  	for i, n = range t.bins {
   768  		if po > n.po {
   769  			continue
   770  		}
   771  		if po < n.po {
   772  			return nil, i
   773  		}
   774  		return n, i
   775  	}
   776  	return nil, len(t.bins)
   777  }
   778  
   779  // need called on (m, max, extra) uses max m out of extra, and then max
   780  // if needed, returns the adjusted counts
   781  func need(m, max, extra int) (int, int, int) {
   782  	if m <= extra {
   783  		return m, max, extra - m
   784  	}
   785  	max += extra - m
   786  	if max <= 0 {
   787  		return m + max, 0, 0
   788  	}
   789  	return m, max, 0
   790  }
   791  
   792  func (t *Pot) String() string {
   793  	return t.sstring("")
   794  }
   795  
   796  func (t *Pot) sstring(indent string) string {
   797  	if t == nil {
   798  		return "<nil>"
   799  	}
   800  	var s string
   801  	indent += "  "
   802  	s += fmt.Sprintf("%v%v (%v) %v \n", indent, t.pin, t.po, t.size)
   803  	for _, n := range t.bins {
   804  		s += fmt.Sprintf("%v%v\n", indent, n.sstring(indent))
   805  	}
   806  	return s
   807  }