github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/util/automaton/sortedIntSet.go (about)

     1  package automaton
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sort"
     7  	"strconv"
     8  )
     9  
    10  // util/automaton/SortedIntSet.java
    11  
    12  // If we hold more than this many states, we swtich from O(N*2)
    13  // linear ops to O(N log(N)) TreeMap
    14  const TREE_MAP_CUTOVER = 30
    15  
    16  /*
    17  Just holds a set of []int states, plus a corresponding []int count
    18  per state. Used by determinize().
    19  
    20  I have to disable hashCode and use string key to mimic Lucene's
    21  custom hashing function here.
    22  */
    23  type SortedIntSet struct {
    24  	values []int
    25  	counts []int
    26  	// hashCode   int
    27  	dict       map[int]int // keys need sort
    28  	useTreeMap bool
    29  	state      int
    30  }
    31  
    32  func newSortedIntSet(capacity int) *SortedIntSet {
    33  	return &SortedIntSet{
    34  		values: make([]int, 0, capacity),
    35  		counts: make([]int, 0, capacity),
    36  	}
    37  }
    38  
    39  // Adds this state ot the set
    40  func (sis *SortedIntSet) incr(num int) {
    41  	if sis.useTreeMap {
    42  		val, ok := sis.dict[num]
    43  		if !ok {
    44  			sis.dict[num] = 1
    45  		} else {
    46  			sis.dict[num] = 1 + val
    47  		}
    48  		return
    49  	}
    50  
    51  	for i, v := range sis.values {
    52  		if v == num {
    53  			sis.counts[i]++
    54  			return
    55  		} else if num < v {
    56  			// insert here
    57  			sis.values = append(sis.values[:i], append([]int{num}, sis.values[i:]...)...)
    58  			sis.counts = append(sis.counts[:i], append([]int{1}, sis.counts[i:]...)...)
    59  			return
    60  		}
    61  	}
    62  
    63  	// append
    64  	sis.values = append(sis.values, num)
    65  	sis.counts = append(sis.counts, 1)
    66  
    67  	if len(sis.values) == TREE_MAP_CUTOVER {
    68  		sis.useTreeMap = true
    69  		for i, v := range sis.values {
    70  			sis.dict[v] = sis.counts[i]
    71  		}
    72  	}
    73  }
    74  
    75  // Removes the state from the set, if count decrs to 0
    76  func (sis *SortedIntSet) decr(num int) {
    77  	if sis.useTreeMap {
    78  		count, ok := sis.dict[num]
    79  		assert(ok)
    80  		if count == 1 {
    81  			delete(sis.dict, num)
    82  			// Fall back to simple arrays once we touch zero again
    83  			if len(sis.dict) == 0 {
    84  				sis.useTreeMap = false
    85  				sis.values = sis.values[:0] // reuse slice
    86  				sis.counts = sis.counts[:0] // reuse slice
    87  			}
    88  		} else {
    89  			sis.dict[num] = count - 1
    90  		}
    91  		return
    92  	}
    93  
    94  	for i, v := range sis.values {
    95  		if v == num {
    96  			sis.counts[i]--
    97  			if sis.counts[i] == 0 {
    98  				limit := len(sis.values) - 1
    99  				if i < limit {
   100  					sis.values = append(sis.values[:i], sis.values[i+1:]...)
   101  					sis.counts = append(sis.counts[:i], sis.counts[i+1:]...)
   102  				} else {
   103  					sis.values = sis.values[:i]
   104  					sis.counts = sis.counts[:i]
   105  				}
   106  			}
   107  			return
   108  		}
   109  	}
   110  
   111  	panic("should not be here!")
   112  }
   113  
   114  func (sis *SortedIntSet) computeHash() *FrozenIntSet {
   115  	// do nothing related to hash
   116  	if sis.useTreeMap {
   117  		if size := len(sis.dict); size > len(sis.values) {
   118  			sis.values = make([]int, 0, size)
   119  			sis.counts = make([]int, 0, size)
   120  		}
   121  		for state, _ := range sis.dict {
   122  			sis.values = append(sis.values, state)
   123  		}
   124  		sort.Ints(sis.values) // keys in map are not sorted
   125  	} else {
   126  		// do nothing
   127  	}
   128  	return sis.freeze(sis.state)
   129  }
   130  
   131  func (sis *SortedIntSet) freeze(state int) *FrozenIntSet {
   132  	c := make([]int, len(sis.values))
   133  	copy(c, sis.values)
   134  	return newFrozenIntSet(c, state)
   135  }
   136  
   137  func (sis *SortedIntSet) String() string {
   138  	var b bytes.Buffer
   139  	b.WriteRune('[')
   140  	for i, v := range sis.values {
   141  		if i > 0 {
   142  			b.WriteRune(' ')
   143  		}
   144  		fmt.Fprintf(&b, "%v:%v", v, sis.counts[i])
   145  	}
   146  	b.WriteRune(']')
   147  	return b.String()
   148  }
   149  
   150  type FrozenIntSet struct {
   151  	values []int
   152  	state  int
   153  }
   154  
   155  func newFrozenIntSet(values []int, state int) *FrozenIntSet {
   156  	return &FrozenIntSet{values, state}
   157  }
   158  
   159  func newFrozenIntSetOf(num, state int) *FrozenIntSet {
   160  	return &FrozenIntSet{
   161  		values: []int{num},
   162  		state:  state,
   163  	}
   164  }
   165  
   166  func (fis *FrozenIntSet) String() string {
   167  	var b bytes.Buffer
   168  	b.WriteRune('[')
   169  	for i, v := range fis.values {
   170  		if i > 0 {
   171  			b.WriteRune(' ')
   172  		}
   173  		b.WriteString(strconv.Itoa(v))
   174  	}
   175  	b.WriteRune(']')
   176  	return b.String()
   177  }