github.com/coyove/common@v0.0.0-20240403014525-f70e643f9de8/goal/main.go (about)

     1  package goal
     2  
     3  import (
     4  	"sync"
     5  )
     6  
     7  type Goal struct {
     8  	goal       uint64
     9  	overflowed map[uint64]uint64
    10  	overflow   uint64
    11  	sync.Mutex
    12  }
    13  
    14  func New() *Goal {
    15  	return &Goal{
    16  		overflowed: make(map[uint64]uint64),
    17  	}
    18  }
    19  
    20  const bit58_6 = 0xffffffffffffffc0
    21  
    22  func (c *Goal) Meet(num uint64) bool {
    23  	c.Lock()
    24  	defer c.Unlock()
    25  
    26  	if num == c.goal {
    27  		c.goal = num + 1
    28  		return true
    29  	}
    30  
    31  	if num < c.goal {
    32  		return false
    33  	}
    34  
    35  	if num-c.goal > 1<<31 {
    36  		return false
    37  	}
    38  
    39  	c.overflow++
    40  	score := uint64(0)
    41  	for i := c.goal; i < num; {
    42  		x, exist := c.overflowed[i&bit58_6]
    43  		if !exist {
    44  			break
    45  		}
    46  
    47  	AGAIN:
    48  		if x&(uint64(1)<<(i&0x3f)) > 0 {
    49  			score++
    50  			if (i+1)&bit58_6 == i&bit58_6 && i < num {
    51  				i++
    52  				goto AGAIN
    53  			}
    54  			i++
    55  		} else {
    56  			break
    57  		}
    58  	}
    59  
    60  	if score == num-c.goal {
    61  		for i := c.goal; i < num; i++ {
    62  			tag := i & bit58_6
    63  			c.overflowed[tag] &= ^(uint64(1) << (i & 0x3f))
    64  			if c.overflowed[tag] == 0 {
    65  				delete(c.overflowed, tag)
    66  			}
    67  		}
    68  		c.goal = num + 1
    69  		return true
    70  	}
    71  
    72  	c.overflowed[num&bit58_6] |= uint64(1) << (num & 0x3f)
    73  	return true
    74  }
    75  
    76  func (c *Goal) Goal() uint64 {
    77  	return c.goal
    78  }
    79  
    80  func (c *Goal) Overflow() int {
    81  	c.Lock()
    82  	defer c.Unlock()
    83  	return len(c.overflowed)
    84  }